Files

152 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Город сверху — генератор OSM и клиент-серверная симуляция
Добавлен серверный режим по [плану](docs/PLAN.md): подготовленные города,
комнаты до 30 наблюдателей, жители по расписанию, общий календарь и голосования,
сохранения и очередь генерации. Браузерный генератор ниже остаётся режимом отладки.
## Эксплуатация
Для запуска через Docker Compose см. [deploy/README.md](deploy/README.md).
Настройки сервера описаны в [server/README.md](server/README.md).
Интерфейс оператора: `/?admin`.
## Сетевая игра
Нужны Node.js 22+ и Rust stable (на Windows — установленный MSVC linker).
Запускать команды из корня репозитория:
```bash
npm ci
npm run demo # готовый город из локального образца OSM, без запросов к Overpass
npm run build
npm run server:dev # http://localhost:3000/?play
```
В списке выберите Бальцерс, задайте ник и создайте комнату. Другие игроки входят
в ту же комнату из списка. Кнопка «Создать город на сервере» открывает выбор
области и запускает отдельную задачу генерации с прогрессом.
Можно экспортировать уже готовый мир и открыть только статику без симуляции:
```bash
npm run export-city -- world.json public/cities/my-city
# http://localhost:3000/?city=/cities/my-city/manifest.json
```
Экспорты не перезаписываются: новая версия города получает новый каталог.
Настройки, API, ограничения LOD и описание сохранений находятся в
[server/README.md](server/README.md).
Проверки: `npm run typecheck`, `npm test`, `npm run server:test`,
`npm run server:load`. Изменение протокола: `npm run proto:generate`.
## Браузерный генератор для отладки
Выделяете на карте небольшой город или район → по данным OSM строится подробная карта
с видом строго сверху: дороги реальной ширины с тротуарами и разметкой, парковки
с машинами, деревья, и **у каждого здания — этажи, комнаты, двери, окна, лестницы
и мебель**, нарисованные простыми геометрическими фигурами, как на плане квартиры.
В отладочном режиме всё работает в браузере: данные берутся из Overpass API, генерация
идёт в Web Worker'ах, готовый мир сохраняется в IndexedDB.
Машины появляются только на парковках и в гаражах; вдоль улиц они не генерируются.
## Запуск
Нужен Node.js 18+.
```bash
npm install
npm run dev # http://localhost:5173/ (пересборка на лету)
npm run build # сборка в dist/ — можно положить на любой статический хостинг
npm run typecheck
```
Для автоматических проверок сетевого клиента нужен Node.js 22+: `npm test`.
Тесты проверяют таймауты, переключение серверов и отмену без обращения к сети.
Данные сначала запрашиваются у `maps.mail.ru`, затем у `overpass-api.de` и
`overpass.private.coffee`. На каждый запрос отводится 45 секунд, включая загрузку
ответа; после ошибки или таймаута используется следующий сервер. Лимит обработки
запроса на стороне Overpass — 30 секунд. Кнопка «Отмена» прерывает запрос и ожидание
перед повтором.
Без интернета можно проверить на образце: «Другие способы» → «Сгенерировать из выгрузки
Overpass» → `samples/balzers-2013.json` (Бальцерс, Лихтенштейн, данные OSM 2013 года).
Генерация из файла без браузера (для отладки генератора):
```bash
npm run cli -- samples/balzers-2013.json 47.058 9.492 47.074 9.518 world.json
```
## Управление
- перетаскивание — сдвиг, колесо / щипок — масштаб, двойной клик — приблизить;
- справа — этаж для всей карты (⌂ — крыши), `PgUp`/`PgDn` или `[` `]`;
- клик по зданию — карточка: вид, этажность (из OSM или оценка), квартиры, спальные места,
свой переключатель этажей только для этого здания;
- «Экспорт мира» в отладочном режиме — весь мир одним файлом `.json.gz`; `export-city` преобразует его в серверный тайловый формат.
## Как устроена генерация
```
Overpass JSON ─► city.ts ──────────────► зоны, дороги, контуры зданий, деревья, парковки
│ classify.ts вид здания (по тегам, POI внутри, landuse, площади) и этажность
▼
interior.ts (в воркерах) ─► этажи: сетка 0.5 м в осях здания
│ схема: секции с подъездами | коридор | простая раскладка
│ деление на комнаты по программе (м²), несколько попыток с оценкой
│ двери = остовное дерево по графу смежности, санузлы и спальни — тупики
│ вход с фасада к дороге, окна с шагом по типу здания
▼
furnish.ts + catalog.ts ──► мебель по правилам для каждого типа комнаты
▼
finalize.ts ──────────────► общие модели предметов, округление до 1 см
```
- **Сид** здания = OSM-id ⊕ сид мира — один и тот же город всегда генерируется одинаково.
- Многоквартирные дома — **секционные**: подъезд с лестницей (и лифтом от 5 этажей),
площадка, 1–4 квартиры вокруг неё; на первом этаже — проход к входу, у домов с магазинами
вместо квартир магазины со своими входами с улицы.
- Офисы, школы, больницы, гостиницы — **коридорная** схема.
- Дома, магазины, кафе, цеха, склады, храмы, гаражи — **простая** раскладка
(у гаражных рядов — отдельные боксы с воротами).
## Модель данных мира (`src/types.ts`)
Статические данные уже используются сервером; для дальнейшего игрового слоя предусмотрены:
| Что | Зачем потом |
|---|---|
| `Door.rooms = [комната, комната \| 'outside']` | рёбра графа навигации внутри здания |
| `Stairs` (одно место на всех этажах, `up`/`down`), лифты | переходы между этажами |
| `Unit` — квартира / магазин / офис с `roomIds` и `beds` | домохозяйства и рабочие места для жителей |
| `Prop.blocksMove`, `Prop.blocksSight`, `tags` (`sleep:2`, `sit:4`, `work`, `cook`, `storage`…) | коллизии, линия обзора, что агент может сделать с предметом |
| `Wall` с разрывами под двери и окна, `Window` | коллизии и видимость (окна прозрачны для взгляда) |
| `Road` с шириной, тротуарами, `oneway`, слоями | граф улиц для перемещения по городу |
| все объекты с `id` | хранение состояния: открытая дверь, взятый предмет |
Координаты — метры в локальной проекции вокруг центра области (x — восток, y — юг).
## Ограничения MVP
- Область до 25 км²; предупреждение о времени генерации — свыше 10 км².
Скорость и расход памяти зависят от плотности застройки и этажности.
Публичные серверы Overpass рассчитаны на умеренную нагрузку; для
публичной игры понадобится своё зеркало или заранее нарезанные данные (например, экстракт
Geofabrik → статические файлы).
- Подвалы, мансарды, балконы, береговая линия морей пока не генерируются.
- Нестандартные контуры (сильно изломанные) дают менее аккуратные планировки.
## Данные и лицензии
Данные карты © участники OpenStreetMap, лицензия ODbL. Если вы распространяете
сгенерированные миры, укажите «© OpenStreetMap contributors». Тайлы на экране выбора
области — стандартные тайлы OSM по их [правилам использования](https://operations.osmfoundation.org/policies/tiles/);
поиск — Nominatim (не чаще раза в секунду).
Идеи частично подсказаны проектом [KnoxMap](https://github.com/spytheeuclidean-a11y/knoxmap);
код написан с нуля.