Fix layout issues in the user interface by adjusting CSS styles for better responsiveness and accessibility. Update component structure to improve maintainability and enhance user experience across different devices.
ci / server (push) Failing after 3m32s
ci / client (push) Successful in 15s

This commit is contained in:
Leonid Pershin
2026-08-18 13:21:41 +03:00
parent cc9efca891
commit d96b420133
6 changed files with 430 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
# Рантайм школы: поток и ECS
Договорённость на ближайшее планирование. Сейчас в коде **не так**: один `GameLoopService`
тикает все школы на одном потоке, и это записано в `AGENTS.md` как инвариант. Ниже — целевая
модель. Менять инвариант в рабочих соглашениях имеет смысл только вместе с кодом.
Экран и defs: [`near-term.md`](near-term.md), [`defs.md`](defs.md).
## Что уже почти есть
У каждой `School` уже свой Arch `World`. Это оставляем и делаем жёстким правилом: мир не
разделяется между школами и не отдаётся чужому потоку. Arch не потокобезопасен.
## Целевая модель
Каждая школа — **актор**: свой поток (или `TaskCreationOptions.LongRunning`, что для нас то же
самое: выделенный поток, не пул тиков), свой `World`, свои часы, свой **замороженный** каталог
def (набор модов, выбранный при создании).
Над ними — тонкий супервизор (сегодняшняя роль `GameLoopService` + `SchoolRegistry`):
- создать / удалить школу, знать лимит;
- держать ящики: `id →` очередь команд этой школы;
- собирать **снимки** для `GET /api/schools` (работник публикует неизменяемое состояние, как
сейчас цикл публикует `SchoolsState`);
- маршрутизировать сокет: `OpenSchool` / `SetRunning` / кадры часов — только в ящик той школы.
Супервизор **не** вызывает `World`, не тикает часы, не читает defs инстанса. Работник **не**
трогает чужой мир и не ходит в ASP.NET.
Тик по-прежнему фиксированный (`SimulationOptions.FixedDeltaTime`), у каждого работника свой
таймер. Школы не синхронизируют календарь друг с другом — так и задумано.
Пока школ максимум шесть, шесть потоков — нормально. Не ставить тик симуляции на `ThreadPool`:
под нагрузкой его заберут запросы и часы начнут плыть.
## Зачем ломать текущий цикл
Один поток на все школы дешевле и проще (нет гонок между мирами). Отдельный поток нужен, когда
школы перестанут быть «только часы»: моды, карта, ECS. Тогда одна тяжёлая школа не должна
останавливать остальные, и набор модов у школы A не должен быть глобальным синглтоном процесса.
Каталог def **на школу**, не на процесс: при создании выбирают моды, работник грузит папки и
больше их не перечитывает. Иначе правка JSON на диске внезапно меняет уже идущую школу.
## Как это стыкуется с сокетом и меню
Как сейчас по смыслу, другое только «кто трогает School»:
- входящее с HTTP/WS → команда в ящик школы (или супервизору, если это create/delete);
- меню читает опубликованный снимок, без блокировки работника;
- исходящие кадры часов — из работника в outbox соединения, не наоборот.
Инвариант вместо «только поток цикла трогает registry» становится: **только работник школы
трогает её `School` / `World` / каталог; супервизор трогает только таблицу ящиков.**
## Пока не делаем
- Потоки на системы внутри одной школы (job system как у RimWorld) — рано.
- Миграция живой школы на другой набор модов.
- Правка `AGENTS.md` до тех пор, пока цикл в коде ещё общий.