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,237 @@
|
||||
# Наём, предметы и бюджет
|
||||
|
||||
Договорённость на следующий срез, не текущий код.
|
||||
Люди: [`people.md`](../02-people/people.md). Типы и карта: [`defs.md`](../01-shell/defs.md).
|
||||
Экран игрока: [`near-term.md`](../01-shell/near-term.md). Проекты: [`projects.md`](../01-shell/projects.md).
|
||||
|
||||
Первый срез, где игрок **что-то решает**. До сих пор школа собиралась сама: генератор закрывал
|
||||
все должности, игрок смотрел. Теперь школа открывается пустой — без единого учителя, — и её
|
||||
надо укомплектовать: нанять людей из пула соискателей, раздать им предметы и уложиться в
|
||||
выделенные деньги.
|
||||
|
||||
Уроков по-прежнему нет. Предмет — это то, что учитель **числится** вести, а не то, что происходит
|
||||
в кабинете. Расписание, звонки и оценки — следующий разговор.
|
||||
|
||||
## Что меняется в уже принятом
|
||||
|
||||
Три решения прошлых срезов приходится поправить. Это не мелочь, поэтому названы отдельно.
|
||||
|
||||
| Было | Стало | Почему |
|
||||
| --- | --- | --- |
|
||||
| Генератор закрывает все должности | Школа стартует без сотрудников | Иначе игроку нечего решать |
|
||||
| Кабинет — таблица именованных слотов | Кабинет — число мест | Никто не будет выбирать, какой стул у доски |
|
||||
| `PETeacher` — отдельная должность | Должность одна, физкультура — предмет | Иначе на каждый предмет заводится должность |
|
||||
|
||||
## Мебель и вместимость
|
||||
|
||||
Вместимость по-прежнему **физическая**: в классе не может сидеть больше учеников, чем стоит парт.
|
||||
Это не меняется — от неё зависит весь ростер.
|
||||
|
||||
Меняется то, как эта мебель задаётся. У кабинета исчезает таблица именованных слотов — «доска»,
|
||||
«стол учителя», «стул учителя», «парты» — и остаётся одно число: сколько парт в кабинете.
|
||||
Выбирать между стулом и креслом у доски игрок не будет никогда, а таблица из четырёх строк на
|
||||
каждый из одиннадцати кабинетов делает редактор нечитаемым.
|
||||
|
||||
Именованные слоты **остаются** там, где обстановка действительно разная: столовая, медкабинет,
|
||||
кабинет директора, библиотека. Там выбор осмыслен — сколько столов, какая кушетка.
|
||||
|
||||
Правило простое: **слоты — там, где есть из чего выбирать; число — там, где важно только сколько.**
|
||||
|
||||
## Предметы
|
||||
|
||||
Новый вид def — `SubjectDef`. Не навык и не работа: навык — это то, что растёт у ребёнка, работа —
|
||||
то, чем занят человек в комнате, а предмет — то, что стоит в дипломе и в нагрузке.
|
||||
|
||||
`SubjectDef` описывает:
|
||||
|
||||
- **какие навыки развивает и насколько** — список пар «навык + доля»;
|
||||
- **в каких параллелях преподаётся**;
|
||||
- **сколько часов в неделю** в каждой из них — учебный план.
|
||||
|
||||
Часы здесь не задел на расписание, а рабочая величина уже этого среза: из них считается нагрузка
|
||||
учителя, а из нагрузки — зарплата. Расписание ([`schedule.md`](../04-schedule/schedule.md)) только расставит эти
|
||||
часы по дням; сколько их — решает учебный план.
|
||||
|
||||
Так «начальные классы» получаются естественно: один предмет, который развивает всё понемногу и
|
||||
преподаётся с первой по четвёртую параллель. Дальше идут предметники: математика с пятой по
|
||||
одиннадцатую, развивает один навык, но сильно.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"defName": "PrimarySchool",
|
||||
"grades": { "min": 1, "max": 4 },
|
||||
"hoursPerWeek": 20,
|
||||
"skills": [
|
||||
{ "skill": "Mathematics", "share": 0.3 },
|
||||
{ "skill": "RussianLanguage", "share": 0.3 },
|
||||
{ "skill": "Literature", "share": 0.2 },
|
||||
{ "skill": "Biology", "share": 0.2 },
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Имена предметов и навыков **намеренно совпадают** там, где это одно и то же слово: `SubjectDef`
|
||||
`Mathematics` и `SkillDef` `Mathematics` — разные def'ы разных видов, но подпись у них одна, потому
|
||||
что локали ключуются по имени. Это то, что нужно: игрок не должен видеть «Математика (предмет)».
|
||||
|
||||
Доли не обязаны давать в сумме единицу — это не проценты, а вес влияния. Ни на что в этом срезе
|
||||
они не влияют; они здесь потому, что предмет без ответа на вопрос «что он развивает» не проверишь,
|
||||
а дописывать поле позже — значит переписывать весь ванильный контент.
|
||||
|
||||
## Учитель
|
||||
|
||||
Должность одна — `Teacher`. Предмет не в должности, а в **назначении**: у нанятого учителя
|
||||
один предмет или несколько.
|
||||
|
||||
Отсюда следует важное: **потребность в учителях больше не берётся из комнат.** Раньше кабинет
|
||||
открывал вакансию «учитель», спортзал — «физрук». Теперь кабинет не открывает ничего: он лишь
|
||||
место, где идёт урок. Школе нужны не «люди в комнатах», а **покрытие предметов по параллелям** —
|
||||
на каждый предмет, преподаваемый в существующих параллелях, нужен хотя бы один учитель.
|
||||
|
||||
Нетренерские должности — директор, секретарь, медсестра, библиотекарь, повар — по-прежнему рождаются
|
||||
из комнат, как описано в [`defs.md`](../01-shell/defs.md). Их игрок тоже нанимает, но предметов им не назначают.
|
||||
|
||||
## Соискатели
|
||||
|
||||
Пул соискателей — **общий** список на школу, не «по трое на вакансию».
|
||||
|
||||
Соискатель — **полноценный человек** со всеми слоями: тело, навыки, черты, семья. Иначе выбирать
|
||||
не из чего: весь смысл в том, чтобы сравнить «математика 78, усидчивый» с «математика 41,
|
||||
вспыльчивый».
|
||||
|
||||
Соискателем **может оказаться родитель ученика** — и это не частный случай, а естественное
|
||||
следствие уже принятого: человек может быть в двух ролях сразу. Нанятый родитель становится
|
||||
работником, оставаясь родителем, и никакой второй сущности для него не заводится.
|
||||
|
||||
Пул **обновляется раз в неделю и не целиком**. Часть людей уходит — нашли работу в другом месте, —
|
||||
часть остаётся искать дальше, приходят новые. Полная замена раз в неделю превращала бы выбор в
|
||||
лотерею: понравившийся кандидат исчезал бы, пока игрок думает.
|
||||
|
||||
Не нанятый и не ушедший остаётся тем же человеком: с тем же именем, теми же навыками и тем же
|
||||
запросом по зарплате. Обновление детерминировано от сида школы и номера недели.
|
||||
|
||||
## Деньги
|
||||
|
||||
**Баланса нет.** Сверху выделяют фиксированную сумму на зарплаты в месяц — не на счёт, а как
|
||||
предел. Ничего не копится, сэкономленное не переносится.
|
||||
|
||||
Значит и правило одно: **месячный фонд оплаты не может превысить выделенную сумму.** Выделили
|
||||
10 000, наняли одного за 3 000 и второго за 7 000 — всё, больше никого. Не «ушли в минус», не
|
||||
«долг», а просто нельзя.
|
||||
|
||||
### Сколько просит человек
|
||||
|
||||
Соискатель называет **цену часа**. Она складывается из двух вещей:
|
||||
|
||||
- **навыки** — сильный предметник стоит дороже слабого;
|
||||
- **черты** — самоуверенный просит больше, зажатый меньше, при тех же навыках.
|
||||
|
||||
Черта, влияющая на запрос, — это поле у `TraitDef`, а не список фамилий в коде. Мод, добавивший
|
||||
«скромный», сразу получает более дешёвого кандидата.
|
||||
|
||||
### Сколько он в итоге стоит
|
||||
|
||||
Месячная зарплата — **цена часа × недельная нагрузка**. Нагрузка не выдумывается: она следует из
|
||||
учебного плана. Назначили человеку математику — он забирает все часы математики во всех
|
||||
параллелях, где она преподаётся, и это может оказаться много.
|
||||
|
||||
Ниже одной ставки (`BaseWeeklyHours`) не платят: нанятый стоит денег, даже если ему ничего не
|
||||
назначили. Иначе набрать полный штат «про запас» было бы бесплатно.
|
||||
|
||||
Отсюда два ограничения вместо одного:
|
||||
|
||||
- **Деньги.** Фонд оплаты не может превысить выделенную сумму. Проверяется при найме и назначении.
|
||||
- **Человек.** Никто не вытянет больше `MaxWeeklyHours` часов. Если часов предмета больше, нужен
|
||||
второй учитель — часы делятся между ними, и первому становится легче и дешевле.
|
||||
|
||||
**Предел часов не запрещает назначение, а помечает предмет непокрытым.** Запрет завёл бы в тупик:
|
||||
первый учитель предмета всегда получает все его часы, поэтому первым не смог бы стать никто.
|
||||
Считать часы «до предела» тоже нельзя — тогда седьмой предмет тому, кто уже за пределом, достаётся
|
||||
бесплатно, а это ровно та дыра, ради которой почасовая оплата и вводилась. Поэтому часы считаются
|
||||
целиком, деньги это показывают, а список непокрытого говорит, что один человек столько не выучит.
|
||||
|
||||
Поэтому «нанять посильнее» и «нагрузить одного вместо двоих» — два разных способа потратить один
|
||||
фонд, и в этом весь выбор среза. Дешёвый учитель, взявший три предмета, упрётся в часы; дорогой
|
||||
с одним предметом съест фонд.
|
||||
|
||||
Цифры — шкала цены часа, влияние черт, предел часов — живут в настройках и в `core`, не в коде.
|
||||
|
||||
## Старт в выходной
|
||||
|
||||
Школа создаётся пустой, и первое, что делает игрок, — нанимает людей. Делать это под тикающие
|
||||
часы учебного дня незачем, поэтому дата по умолчанию переезжает с вторника **3 апреля 2012** на
|
||||
субботу **31 марта 2012**: у игрока есть выходные, чтобы собрать штат до того, как в понедельник
|
||||
придут дети.
|
||||
|
||||
Учебный год при этом тот же, ростер не меняется.
|
||||
|
||||
## Экран
|
||||
|
||||
Не третья вкладка в панели и не модальное окно. Под часами появляется **два верхних раздела**:
|
||||
|
||||
| Раздел | Что в нём |
|
||||
| --- | --- |
|
||||
| **Обзор** | Всё, что есть сейчас: карта / люди слева, просмотр выбранного справа |
|
||||
| **Управление** | Деньги, соискатели, штат и назначение предметов |
|
||||
|
||||
Верхние разделы, а не вкладки внутри панели, потому что управление — это другой режим работы, а
|
||||
не ещё один список. Часы и дата остаются на месте в обоих: наём идёт по игровому времени, пул
|
||||
обновляется по неделям, и прятать календарь на время найма нельзя.
|
||||
|
||||
Внутри «Управления» та же схема, что и в «Обзоре»: список слева, карточка справа. Карточка
|
||||
соискателя — та же карточка человека, что и в «Людях»; он и есть человек, просто пока не ваш.
|
||||
|
||||
Сверху — одна строка про деньги: выделено, расписано, свободно. Ниже — непокрытые предметы,
|
||||
соискатели и нанятый штат.
|
||||
|
||||
## Советы, которые стоит принять сразу
|
||||
|
||||
- Не заводить должность на каждый предмет. Иначе `PositionDef` превращается в справочник
|
||||
специальностей, а назначение предмета становится увольнением и повторным наймом.
|
||||
- Не делать баланс, пока сверху приходит фиксированная сумма. Баланс — это уже экономика:
|
||||
накопления, долги, проценты. Здесь нужен предел, а предел — одно число.
|
||||
- Не обновлять пул целиком. Кандидат, исчезнувший, пока игрок его разглядывал, читается как баг.
|
||||
- Не выкидывать не нанятых людей в ростер школы. Соискатель — не сотрудник и не житель школы;
|
||||
в ростер он попадает только при найме.
|
||||
- Проверять предел в момент действия, а не в конце месяца. «Нельзя нанять» игрок понимает,
|
||||
«в конце месяца что-то случилось» — нет.
|
||||
|
||||
## Заведомо не сейчас
|
||||
|
||||
- Само расписание: когда именно идут эти часы. Следующий срез, [`schedule.md`](../04-schedule/schedule.md).
|
||||
Здесь предмет — нагрузка в часах, а не событие в кабинете.
|
||||
- Уроки, звонки, оценки, посещаемость.
|
||||
- Классное руководство: класс закреплён за кабинетом, но не за учителем.
|
||||
- Увольнение и уход по собственному желанию.
|
||||
- Переговоры о зарплате, повышения, стаж.
|
||||
- Любые траты, кроме зарплат: ремонт, закупки, коммуналка.
|
||||
- Накопление денег, долги, штрафы.
|
||||
- Требования к диплому: любой нанятый может вести любой предмет, вопрос только в его навыке.
|
||||
|
||||
## Зафиксировано этим разговором
|
||||
|
||||
| Тема | Решение |
|
||||
| --- | --- |
|
||||
| Старт школы | Без сотрудников вообще; игрок нанимает всех |
|
||||
| Стартовая дата | Суббота 31 марта 2012 — выходные на сборку штата |
|
||||
| Вместимость класса | По-прежнему физическая: не больше учеников, чем парт |
|
||||
| Кабинет | Одно число мест вместо таблицы именованных слотов |
|
||||
| Слоты | Остаются там, где обстановка разная: столовая, медкабинет, кабинет директора |
|
||||
| Должность учителя | Одна, `Teacher`; `PETeacher` упраздняется |
|
||||
| Предмет | Новый `SubjectDef`: какие навыки развивает и в каких параллелях |
|
||||
| Начальные классы | Предмет, развивающий всё понемногу, параллели 1–4 |
|
||||
| Назначение | У учителя один предмет или несколько |
|
||||
| Потребность в учителях | Покрытие предметов по параллелям, а не вакансии в комнатах |
|
||||
| Прочие должности | По-прежнему из комнат; игрок нанимает и их |
|
||||
| Соискатель | Полноценный человек; может быть родителем ученика |
|
||||
| Пул | Общий, обновляется раз в неделю частично, детерминированно |
|
||||
| Учебный план | Часы в неделю по параллелям — поле `SubjectDef`, а не задел |
|
||||
| Запрос по деньгам | Цена часа: от навыков и от черт (самоуверенный просит больше) |
|
||||
| Зарплата | Цена часа × недельная нагрузка из учебного плана, но не меньше одной ставки |
|
||||
| Деление часов | Учителя одного предмета делят его часы поровну |
|
||||
| Предел нагрузки | `MaxWeeklyHours` не запрещает назначение, а делает предмет непокрытым |
|
||||
| Непокрытый предмет | Нет учителя **или** назначенные не вытягивают его часы |
|
||||
| Бюджет | Фиксированная сумма в месяц из настроек; баланса нет |
|
||||
| Предел | Фонд оплаты не может превысить выделенное; проверка в момент действия |
|
||||
| Экран | Два верхних раздела под часами: «Обзор» и «Управление» |
|
||||
| Внутри управления | Список слева, карточка человека справа — та же, что в «Людях» |
|
||||
Reference in New Issue
Block a user