Remove off-queue.md and add new design documentation files including README.md, defs.md, near-term.md, projects.md, runtime.md, people.md, staffing.md, and schedule.md to outline the structure and agreements for the game's design phases.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
# Фаза 48. Учитель в кабинете
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 21](../05-ai/21-decisions.md)
|
||||
- [Фаза 18](../05-ai/18-presence-walking.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
Ученик в кабинете больше не качает навык в пустоту. Нет учителя на месте — нет роста.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] `LessonLearningSystem` растёт навык, только если назначенный учитель стоит в
|
||||
`lesson.RoomId`: на кампусе, путь пуст, остаток минут 0
|
||||
- [x] Нет человека с `TeacherId` в мире — как отсутствующий
|
||||
- [x] Действие учителя урок не отменяет
|
||||
- [x] Формула `LessonLearning.Gain` не меняется
|
||||
- [x] Лог ученика `lesson-no-teacher` один раз на предмет в сутки, не каждый тик; `thingDef` —
|
||||
предмет; подпись из каталога
|
||||
- [x] `docs/protocol.md` — новый `type` у HTTP лога, без бампа сокета
|
||||
- [x] Фикстуры, где учитель был строкой `t1` вне ростера, нанимают живого человека — иначе
|
||||
существующий тест роста навыка зелёный впустую
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Ученик и учитель стоят в кабинете → навык за урок вырос
|
||||
- [x] Ученик в кабинете, учитель в другом узле → навык не вырос
|
||||
- [x] Учитель идёт по коридору в этот кабинет → пока идёт, роста нет
|
||||
- [x] Нет человека с id учителя → роста нет
|
||||
- [x] За урок без учителя в логе ученика одна строка `lesson-no-teacher`, не по числу тиков
|
||||
- [x] Голодный по-прежнему учится хуже сытого, когда учитель на месте
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Учитель ушёл в туалет посреди математики — класс в кабинете есть, навык за эти минуты не
|
||||
ползёт
|
||||
- `dotnet test` проходит
|
||||
|
||||
## Стоп
|
||||
|
||||
Не масштабировать рост навыком учителя. Не трогать тепло, учебник и дорогу. Не бампить
|
||||
протокол. Не писать лог учителю.
|
||||
@@ -0,0 +1,45 @@
|
||||
# Фаза 49. Пропуск сборки при запуске
|
||||
|
||||
## Зависимости
|
||||
|
||||
Нет. Скрипт запуска уже есть.
|
||||
|
||||
## Зачем
|
||||
|
||||
Повторный `run-aspire.cmd` без правок в C# не должен ждать MSBuild графа Aspire. Сборка нужна
|
||||
только когда входы новее dll или когда просили `--rebuild`.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] `tools/apphost-uptodate.ps1`: выход 0, если AppHost и Server dll новее входов; 1 — если
|
||||
нет dll или вход новее. Входы: `*.cs` / `*.csproj` / `*.props` под `src/` без `bin` /
|
||||
`obj` / `node_modules`, плюс `global.json`, `Directory.Build.props`, `Directory.Packages.props`.
|
||||
TypeScript и JSONC не входы
|
||||
- [x] `run-aspire.cmd` вызывает проверку; при 0 — `dotnet run --no-build` и пишет, что сборка
|
||||
пропущена; иначе `dotnet build`, затем `--no-build`. `--rebuild` всегда собирает и не
|
||||
уходит в AppHost. `-c` / `--configuration` выбирают папку `bin`
|
||||
- [x] `LaunchBuildStamp` с теми же правилами, тесты на временных папках без `AppHostFixture`
|
||||
- [x] `AGENTS.md` и `README.md`: повторный запуск без правок — `run-aspire.cmd`; голый
|
||||
`dotnet run` по-прежнему собирает. `--rebuild` упомянут
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Нет dll — нужно собирать
|
||||
- [x] Dll новее всех входов — пропускать
|
||||
- [x] `.cs` новее dll — собирать
|
||||
- [x] `.ts` или `.jsonc` новее dll — пропускать
|
||||
- [x] Файл в `bin` / `obj` / `node_modules` не считается входом
|
||||
- [x] `Directory.Packages.props` новее dll — собирать
|
||||
- [x] `-c Release` смотрит `bin/Release`, а не Debug
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Два запуска `run-aspire.cmd` подряд без правок: второй пишет, что сборка пропущена, и
|
||||
стартует AppHost
|
||||
- `run-aspire.cmd --rebuild` собирает даже со свежими dll
|
||||
- `dotnet test` проходит; тесты штампа не поднимают хост
|
||||
|
||||
## Стоп
|
||||
|
||||
Не менять Aspire-граф, протокол, сейвы. Не вшивать `--no-build` в голый `dotnet run`. Не
|
||||
сканировать `tests/` и не считать клиентский TS поводом пересобрать сервер.
|
||||
@@ -0,0 +1,34 @@
|
||||
# Фаза 50. Навык учителя на уроке
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 48](48-lesson-teacher-present.md)
|
||||
- [Фаза 12](../03-staffing/12-hiring-budget.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
Соискатель с математикой 78 перестаёт отличаться от 41 только зарплатой.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] `LessonLearning.TeacherFactor` — та же кривая, что `NeedFactor`: навык 0 → 0.25, 100 → 1
|
||||
- [x] Навык учителя — среднее его значений по `SubjectDef.skills`; нет ключа — `Range.Min`
|
||||
- [x] `Gain` умножает на этот фактор; учитель в кабинете по-прежнему обязателен (фаза 48)
|
||||
- [x] Числа кривой в коде рядом с нуждой, не новый экран и не сейв
|
||||
- [x] Лог не пишем: рост тише — это и есть сигнал
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Учитель с навыком 20 даёт меньший прирост, чем с 80, при том же ученике и голоде
|
||||
- [x] Предмет с несколькими скиллами берёт среднее, а не первый попавшийся в словаре
|
||||
- [x] Нет ключа навыка у учителя — подставляется минимум шкалы, рост не падает в ноль
|
||||
- [x] Учителя нет в кабинете — по-прежнему нулевой рост, фактор не спасает
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Два учителя математики в тестовой школе: слабый класс растёт заметно медленнее
|
||||
- `dotnet test` проходит
|
||||
|
||||
## Стоп
|
||||
|
||||
Не вводить оценки. Не менять формулу зарплаты. Не трогать тепло и учебник.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Фаза 51. Тепло на уроке
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 48](48-lesson-teacher-present.md)
|
||||
- [Фаза 32](../07-inventory/32-weather-warmth.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
Замёрзший сидит на уроке так же, как голодный: полоска уже есть, рост её должен чувствовать.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] `Gain` умножает `NeedFactor(голод) × NeedFactor(тепло)`
|
||||
- [x] Нет нужды `Warmth` в каталоге — множитель тепла 1, голод как сейчас
|
||||
- [x] Лог `lesson-cold` один раз на предмет в сутки, если на уроке, который иначе учил,
|
||||
тепло ниже `BehaviorDef.needThreshold`; `thingDef` — предмет
|
||||
- [x] `docs/protocol.md` — тип лога
|
||||
- [x] В [`inventory.md`](../../design/07-inventory/inventory.md) убрать «тепло урок не штрафует»: стало рядом
|
||||
с голодом
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Тепло 0.1 и голод 1 → меньший прирост, чем оба по 1
|
||||
- [x] Тепло 1 и голод 0.1 → как нынешний голодный, тепло не «вылечивает»
|
||||
- [x] Нет `Warmth` в каталоге — голодный тест фазы 21 по-прежнему зелёный
|
||||
- [x] За урок на холоде одна строка лога, не по числу тиков
|
||||
- [x] Учителя нет в кабинете — лога холода нет (урок не учил)
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Январь без техника: полоска тепла падает, навык за тот же урок растёт медленнее, чем в мае
|
||||
- `dotnet test` проходит
|
||||
|
||||
## Стоп
|
||||
|
||||
Не болеть от промокания. Не штрафовать ходьбу. Не трогать учебник.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Фаза 52. Учебник на уроке
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 48](48-lesson-teacher-present.md)
|
||||
- [Фаза 35](../07-inventory/35-appropriateness.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
Утренний `RepackBag` уже кладёт учебники сегодняшних предметов в сумку. Урок начинает это
|
||||
проверять.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] Рост урока полный, только если в **сумке** есть экземпляр с `subject` этого предмета
|
||||
- [x] Шкафчик и дом не считаются: ученик в кабинете
|
||||
- [x] Нет учебника — множитель `BehaviorDef.lessonNoTextbookFactor`, ваниль 0.5
|
||||
- [x] Валидатор: число 0–1
|
||||
- [x] Лог `lesson-no-textbook` один раз на предмет в сутки; `thingDef` — предмет
|
||||
- [x] `docs/protocol.md` — тип лога
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Учебник математики в сумке → полный рост (при учителе на месте)
|
||||
- [x] Тот же учебник в шкафчике или дома → рост как с коэффициентом 0.5
|
||||
- [x] Учебник другого предмета в сумке не закрывает этот урок
|
||||
- [x] Одна строка лога за сутки на предмет, не по числу тиков
|
||||
- [x] Пак без поля — 0.5, каталог не падает
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Слабая переноска, учебник остался дома — на уроке растут хуже одноклассника с книгой
|
||||
- `dotnet test` проходит
|
||||
|
||||
## Стоп
|
||||
|
||||
Не заставлять идти за учебником отдельной целью. Не замедлять ходьбу перегрузом. Не тратить
|
||||
деньги на замену.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Фаза 53. Погода на дороге
|
||||
|
||||
## Зависимости
|
||||
|
||||
- [Фаза 18](../05-ai/18-presence-walking.md)
|
||||
- [Фаза 32](../07-inventory/32-weather-warmth.md)
|
||||
|
||||
## Зачем
|
||||
|
||||
В январе опаздывают чаще, чем в мае. Черта уже двигает запас на дорогу; осадки — тоже.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] `BehaviorDef.commuteRainMinutes` и `commuteSnowMinutes`; ваниль 3 и 6
|
||||
- [x] Валидатор: не отрицательные
|
||||
- [x] `DayPlans.Build` принимает уже посчитанные лишние минуты; `HSchool.Ai` не знает осадков
|
||||
- [x] Симуляция при сборке плана дня подставляет минуты из текущей улицы
|
||||
- [x] Лог на каждого не пишем — опоздание видно местом
|
||||
- [x] В [`inventory.md`](../../design/07-inventory/inventory.md) поправка: погода влияет на дорогу, не только
|
||||
на переодевание
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Снег → `AppearAt` раньше на `commuteSnowMinutes` относительно ясного того же дня
|
||||
(тот же человек, сид, дата без осадков)
|
||||
- [x] Дождь → на `commuteRainMinutes`
|
||||
- [x] Ясно → минуты как сейчас, только черты и бросок
|
||||
- [x] Пак без полей — 0 лишних минут, каталог не падает
|
||||
- [x] Тот же сид и снег → тот же `AppearAt`
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Снежным утром класс наполняется позже, чем ясным; ленивый по-прежнему ближе к звонку
|
||||
- `dotnet test` проходит
|
||||
|
||||
## Стоп
|
||||
|
||||
Не мочить одежду. Не пропускать день из-за мороза. Не бампить кадр часов.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Фаза 54. Что нового
|
||||
|
||||
## Зависимости
|
||||
|
||||
Нет. Сессия (фаза 38) уже ставит куку входа; это отдельная кука и отдельное окно.
|
||||
|
||||
## Зачем
|
||||
|
||||
После наката игрок не обязан читать git. Окно один раз показывает, что изменилось с прошлого
|
||||
захода в этот браузер.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] Сборка Server вшивает SHA и `git log --first-parent` (не вызов git в рантайме)
|
||||
- [x] `GET /api/changelog?since=` с сессией: текущий SHA и коммиты строго после `since`
|
||||
- [x] Нет `since`, неизвестный SHA, `since` = текущий — `commits` пустой
|
||||
- [x] Subject `Mark phase N…` в окне нет; в цепочке якоря они остаются
|
||||
- [x] Кука `hschool.seen-rev` (не HttpOnly, не сессионная): первый заход молча запоминает HEAD
|
||||
- [x] Модалка только после `ensureSession` (вход и повторный вход после logout), не с меню школы
|
||||
- [x] [`protocol.md`](../../protocol.md) HTTP, версию сокета не бампить
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Срез после известного SHA — видимые коммиты старше→новее, без `Mark phase`
|
||||
- [x] Якорь на `Mark phase` — следующие видимые всё равно отдаются
|
||||
- [x] Нет `since` / неизвестный SHA / `since` = текущий — пустой список
|
||||
- [x] `GET /api/changelog` без сессии — `401`
|
||||
- [x] С сессией без `since` — 40 hex в `current`, `commits` пустой
|
||||
- [x] Нет куки — запрос без `since`, кука = `current`, диалога нет
|
||||
- [x] Кука старше, сервер вернул коммиты — диалог, по закрытию кука = `current`
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Первый заход после деплоя с новой сборкой Server показывает окно; повторный заход в том же
|
||||
браузере — нет
|
||||
- `run-aspire` без `--rebuild` после коммита только в доках может показать старый SHA: вшито
|
||||
на сборке, не HEAD рабочего дерева
|
||||
|
||||
## Стоп
|
||||
|
||||
Не писать last-seen в `users.json`. Не бампить сокет. Не вызывать git из бегущего сервера.
|
||||
Не показывать окно при возврате из школы на меню.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Фаза 55. Состояние экрана
|
||||
|
||||
## Зависимости
|
||||
|
||||
Нет. Оболочка, люди, управление и соискатели уже на экране.
|
||||
|
||||
## Зачем
|
||||
|
||||
F5 и выход в меню не должны выкидывать игрока на карту с пустыми фильтрами. Школа, вкладки и
|
||||
уже существующие поиски/фильтры восстанавливаются; сервер по-прежнему единственный источник
|
||||
игровых данных.
|
||||
|
||||
## Задачи
|
||||
|
||||
- [x] Query URL: `school`, `mode`, `tab`, `node`, `person`, `inspect`. F5 с `school=` снова
|
||||
открывает эту школу (`OpenSchool` как с карточки меню). Нет школы / не в списках — меню,
|
||||
URL чистится. Гость с `mode=manage` остаётся в обзоре
|
||||
- [x] `sessionStorage` ключ `h-school.view.{id}`: фильтры и пейджер людей, поиск/фильтры
|
||||
соискателей, вкладка и поиски карточки, вкладка управления и выбранный класс сетки,
|
||||
последний `mode`/`tab`/выбор — чтобы повторный вход с меню поднял то же место
|
||||
- [x] `history.pushState` только вход и выход; смена вкладки и фильтров — `replaceState`.
|
||||
«Назад» из школы — меню. Протокол, HTTP и сейв не трогать; роутер не добавлять
|
||||
- [x] Подписи через `t(...)` не нужны: новых строк нет. `docs/design/off-queue/view-state.md` и эта фаза —
|
||||
в том же коммите, что и код
|
||||
|
||||
## Тесты, без которых фаза не закрыта
|
||||
|
||||
- [x] Разбор и сборка query: валидные поля, мусорный `mode`/`school` → обзор / меню
|
||||
- [x] Chrome в `sessionStorage` пишется и читается по школе; битый JSON → значения по умолчанию
|
||||
- [x] Школа из списка: своя, чужая (`mine: false`), нет id → `null`
|
||||
- [x] Панель людей: `show` поднимает сохранённые фильтры в запрос; смена фильтра пишет storage
|
||||
- [x] Экран школы: URL `tab=people` открывает людей; гость игнорирует `mode=manage`
|
||||
- [x] Управление: новая панель на той же школе открывает сохранённую вкладку «Правила»
|
||||
|
||||
## Критерий готовности
|
||||
|
||||
- Открыть школу, вкладка «Люди», фильтр «ученики / 5», карточка. F5 — снова эта школа, те же
|
||||
фильтры и человек. Назад — меню. Снова открыть ту же школу с меню — те же вкладка и фильтры
|
||||
- Гость не попадает в «Управление» по URL
|
||||
- `npm --prefix src/HSchool.Client test` проходит на затронутых тестах
|
||||
|
||||
## Стоп
|
||||
|
||||
Не класть состояние на сервер. Не бампить протокол. Не добавлять поиск по имени в списки, где
|
||||
его нет. Не держать открытым диалог соискателей и мастер создания. Не трогать скорость часов и
|
||||
паузу — они уже на сервере.
|
||||
@@ -0,0 +1,21 @@
|
||||
Индекс срезов: [`../README.md`](../README.md).
|
||||
|
||||
## Вне очереди
|
||||
|
||||
Дизайн: [`../design/off-queue.md`](../../design/off-queue/README.md).
|
||||
|
||||
Склейка уже живых систем и мелкий DX, не новый кусок игры. Номера не спорят с именованными
|
||||
срезами. После каждой игровой фазы школа целая. 50–52 стоят на 48; 53 — на 18 и 32, можно
|
||||
параллельно с 48. 49, 54 и 55 от них не зависят. Баг в уже сделанном —
|
||||
[`../bugs/README.md`](../../bugs/README.md).
|
||||
|
||||
| Фаза | Статус | Зачем |
|
||||
| --- | --- | --- |
|
||||
| [48. Учитель в кабинете](48-lesson-teacher-present.md) | ✅ | Нет учителя на месте — нет роста навыка |
|
||||
| [49. Пропуск сборки при запуске](49-skip-stale-build.md) | ✅ | `run-aspire.cmd` не гоняет MSBuild, если dll свежие |
|
||||
| [50. Навык учителя](50-teacher-skill-gain.md) | ✅ | Соискатель 78 учит лучше, чем 41 |
|
||||
| [51. Тепло на уроке](51-warmth-lesson.md) | ✅ | Замёрзший учится хуже, как голодный |
|
||||
| [52. Учебник на уроке](52-textbook-lesson.md) | ✅ | Нет в сумке — половинный рост |
|
||||
| [53. Погода на дороге](53-weather-commute.md) | ✅ | Снег и дождь добавляют минуты к приходу |
|
||||
| [54. Что нового](54-whats-new.md) | ✅ | После входа — окно коммитов с прошлого визита |
|
||||
| [55. Состояние экрана](55-view-state.md) | ✅ | F5 и переходы не сбрасывают школу, вкладки и фильтры |
|
||||
Reference in New Issue
Block a user