# Расписание Договорённость на срез после штата, не текущий код. Штат и предметы: [`staffing.md`](staffing.md). Люди: [`people.md`](people.md). Типы и карта: [`defs.md`](defs.md). Экран: [`near-term.md`](near-term.md). Часы из учебного плана раскладываются по дням и кабинетам. Школа впервые начинает **жить по времени**: в 10:15 у 5Б математика в кабинете 204, и это видно на карте. ## Зачем это раньше ходьбы Расписание закрывает дыру, которая тянется с первого среза: в панели локации пустуют «Персонажи» и «Сейчас». Заполнить их можно **без системы перемещения** — если урок стоит в расписании, мы знаем, кто в кабинете и чем занят. Ни поиска пути, ни шагов по коридору: таблица и часы. Люди по-прежнему не ходят. Они **находятся** там, где их застало расписание. ## Каркас дня В `core`, дефом: первый урок в 8:30, до семи уроков, урок 45 минут, перемены по 10 с одной большой на 20. Одна смена. Длина недели — **в настройках**, а не в контенте: пять дней по умолчанию. Это школьное правило, а не свойство мира, и его меняют, чтобы посмотреть, что будет. Каникулы — дефами: осенние, зимние, весенние и лето, диапазонами дат внутри учебного года. В каникулы расписание не действует, школа стоит. ## Учебный план Уже есть: `SubjectDef` знает, в каких параллелях преподаётся предмет и сколько часов в неделю. Расписание ничего не решает про количество — только про расстановку. ## Кто его строит **Сервер, сам, детерминированно** — из учебного плана, назначений и карты. Игрок не раскладывает пасьянс на одиннадцать классов; он влияет тем, кого нанял и что назначил. Но игрок **может править** готовое: передвинуть урок, поменять кабинет. Отсюда правило, без которого правки будут пропадать: **исправленное игроком закрепляется.** Перестроение — а оно случается при каждом найме и назначении — сохраняет закреплённые уроки и пересобирает только остальное. Иначе первый же наём стёр бы всю ручную работу. Снять закрепление игрок может явно; тогда урок снова участвует в общей раскладке. ## Правила раскладки Четыре запрета, нарушать которые нельзя: 1. **Учитель не в двух местах.** Один человек — один урок в слоте. 2. **Класс не в двух местах.** Один класс — один урок в слоте. 3. **Кабинет не занят дважды.** Два класса в одной комнате одновременно невозможны. 4. **Класс влезает в кабинет.** Учеников не больше, чем мест. Урок идёт **не обязательно в своём кабинете**. У предмета может быть требование к типу помещения: физкультура — в спортзале, информатика — в компьютерном классе. Без требования урок идёт в кабинете, закреплённом за классом. Это и делает карту нужной: один спортзал на одиннадцать классов — узкое место, которое видно в расписании, а не в отчёте. ## Некому вести — урока нет Предмет без учителя не ставится вовсе. В расписании класса на этом месте пусто, а в разделе «Управление» предмет числится непокрытым. Так наём получает прямое последствие: нанял человека, назначил ему предмет — в расписании появились уроки. Это единственная обратная связь среза, и она должна быть мгновенной. То же самое, если часов больше, чем вытягивают нанятые: лишние часы просто не встают. ## Что видит игрок **В дереве карты** — что происходит в комнате прямо сейчас, скобками рядом с названием: ``` Этаж 2 Кабинет 204 (Математика · 5Б) Кабинет 205 (Физика · 9А) Кабинет 206 ``` Так классы не сливаются в одинаковые строчки: комната подписана тем, что в ней идёт. Пусто — значит свободна. **В панели локации** — «Сейчас» и «Персонажи» наконец не пустуют: урок, класс, учитель. **В «Управлении»** — расписание класса: сетка «день × урок» на одну параллель. **В карточке учителя** — его личное расписание: где он и когда. Это же карточка, что и в «Людях», так что расписание видно всюду, где человек открывается. Общей сетки на всю школу нет: одиннадцать классов на шесть дней не читаются с экрана, а нужны они только тому, кто раскладывает вручную, — а раскладывает сервер. ## Где это живёт Планировщик — **отдельная библиотека**, как `HSchool.People`: зависит от `HSchool.Content`, не знает ни Arch, ни ASP.NET, отдаёт простую таблицу. Причина та же, что и с генератором людей: то, что строится по детерминированным правилам, проверяется только тестами — «этот штат и эта карта дают вот такую раскладку», — а тест не должен поднимать хост. Расписание сохраняется вместе с составом: оно дешевле пересчитывается, чем восстанавливается, но ручные правки восстановить нельзя. Пишется по тем же правилам, что и ростер — при изменении, а не по таймеру. ## Советы, которые стоит принять сразу - Не давать игроку раскладывать всё вручную. Автоматика с правками — это управление; пустая сетка на 66 ячеек — это работа завуча. - Не пересобирать расписание на каждый тик. Оно меняется от найма и назначения, а не от времени. - Не хранить «кто где сейчас» отдельным состоянием. Это вычисляется из расписания и часов; вторая копия немедленно разойдётся с первой. - Не ставить урок, который некому вести. Дыра в расписании честнее, чем урок без учителя. - Требование к типу помещения — у предмета, а не у комнаты. Комната не знает, что в ней физкультура. ## Заведомо не сейчас - Перемещение по карте: люди находятся в комнате, но не идут в неё. - Оценки, посещаемость, домашние задания, успеваемость. - Замены заболевшего учителя. - Вторая смена, деление класса на подгруппы (языки, труд). - Четверти, триместры, экзамены. - Кружки, продлёнка, всё вне уроков. - Предпочтения учителей: «не ставьте мне первым уроком». ## Зафиксировано этим разговором | Тема | Решение | | --- | --- | | Кто строит | Сервер, детерминированно, из плана и назначений | | Правки игрока | Можно; исправленное закрепляется и переживает перестроение | | Каркас дня | `core`: 8:30, до 7 уроков, 45 минут, перемены 10 и одна 20; одна смена | | Длина недели | В настройках, пять дней по умолчанию | | Каникулы | Дефами, диапазонами дат; в каникулы расписания нет | | Учебный план | Часы из `SubjectDef`, расписание их только расставляет | | Запреты | Учитель, класс и кабинет — не более одного урока в слоте; класс влезает в кабинет | | Место урока | Кабинет класса, если у предмета нет требования к типу помещения | | Нет учителя | Урок не ставится; предмет числится непокрытым | | Карта | В дереве рядом с комнатой — что и у кого там сейчас | | Панель локации | «Сейчас» и «Персонажи» заполняются из расписания — с срезом 5 из присутствия, см. [`ai.md`](ai.md) | | Расписание класса | В разделе «Управление», сетка «день × урок» | | Расписание учителя | В его карточке, там же где навыки и семья | | Общая сетка школы | Не делаем: её читает только тот, кто раскладывает вручную | | Где живёт код | Отдельная библиотека рядом с `HSchool.People` | | Люди и место | Находятся по расписанию; ходьбы нет — отменено срезом 5, присутствие стало состоянием ([`ai.md`](ai.md)) |