README.md + SETUP_GUIDE.md — документация по образцу РВС

README: назначение/контекст, политика закрытого контура, архитектура,
стек, структура репо, БД (21 таблица), матмодель (контрольные точки),
OSM-геослой, API (12 роутеров), фронт, RBAC (142 юнита, 4 роли/9 прав),
мультипоиск, интеграция КОНТУР, аудит, планы.
SETUP_GUIDE: 18 разделов — требования, Docker, .env (смена секретов),
миграции/сиды, импорт OSM в PostGIS, проверки, пользователи, КОНТУР,
прокси/HTTPS, обновление (up -d для env!), бэкапы, диагностика (11 типовых
проблем), чек-лист развёртывания.
This commit is contained in:
2026-09-09 23:09:03 +03:00
parent 9115a0e7af
commit c44bc46667
2 changed files with 773 additions and 0 deletions
+387
View File
@@ -0,0 +1,387 @@
# ВЕКТОР МЧС — Система определения приоритетных направлений поиска
**Программное средство поддержки принятия решений при поисково-спасательных работах (ПСР) на открытой местности МЧС Республики Беларусь.**
ВЕКТОР рассчитывает приоритетные направления поиска пропавшего человека по матмодели: на основании данных о потерявшемся (возраст, диагнозы, физподготовка, транспорт), обстоятельствах потери (время, причина, направление), среде (рельеф, погода, сезон) и точке последней пропажи (ТНП) система строит концентрическую зону вероятного нахождения и подсвечивает приоритетные направления обследования с учётом рельефа из OSM-данных.
> **Версия документа:** соответствует состоянию репозитория на 9 сентября 2026 г.
> **Репозиторий:** [`Sadmin/vector`](http://192.168.0.106:3000/Sadmin/vector)
> **Развёртывание:** см. [SETUP_GUIDE.md](SETUP_GUIDE.md) — пошаговый гайд по развёртыванию на серверах МЧС.
---
## Оглавление
1. [Назначение и контекст](#1-назначение-и-контекст)
2. [Ключевая политика: полностью закрытый контур](#2-ключевая-политика-полностью-закрытый-контур)
3. [Архитектура](#3-архитектура)
4. [Стек технологий](#4-стек-технологий)
5. [Структура репозитория](#5-структура-репозитория)
6. [База данных](#6-база-данных)
7. [Математическая модель расчёта](#7-математическая-модель-расчёта)
8. [OSM-геослой (PostGIS)](#7-osm-геослой-postgis)
9. [Бэкенд (FastAPI) — структура и API](#8-бэкенд-fastapi--структура-и-api)
10. [Фронтенд (React)](#9-фронтенд-react)
11. [Аутентификация, роли и подразделения (RBAC)](#10-аутентификация-роли-и-подразделения-rbac)
12. [Мультипоиск и операции](#11-мультипоиск-и-операции)
13. [Интеграция с КОНТУР (отправка зон)](#12-интеграция-с-контуром-отправка-зон)
14. [Аудит](#13-аудит)
15. [Тестирование](#14-тестирование)
16. [Справочники](#14-справочники)
17. [Что готово и что в планах](#15-что-готово-и-что-в-планах)
18. [Контакты и сопровождение](#16-контакты-и-сопровождение)
---
## 1. Назначение и контекст
### Что делает ВЕКТОР
ВЕКТОР — рабочий инструмент РЦУ (расчётно-центрального управления) МЧС Республики Беларусь при организации поиска пропавших людей:
- **Карточка поиска** — структурированный ввод данных: субъект (возраст, пол, диагнозы — РАС, эпилепсия, СДВГ, ЗПР, психотип), обстоятельства (причина потери, время, направление движения, надёжность свидетельства), среда (сезон, погода, температура, рельеф), ресурсы (группы, кинолог, транспорт)
- **Матрасчёт** — детерминированный расчёт: максимальный радиус по методике ПСР (КМЧ × коэффициенты), приоритетные направления (сектора 45° с весами), прогноз поведения по психотипу, срочность и критические действия
- **Карта зон** — Leaflet: концентрические круги возможной зоны (0.5R / 0.75R / R) + подсветка приоритетных направлений; слои воды/болот полигонами и ж/д линий из локальной OSM
- **Рекомендации** — тактические рекомендации по профилям случая (проверить водоёмы, обследовать вдоль дорог и т.д.)
- **Мультипоиск** — несколько одновременных поисков, каждое ОУМЧС/Г(Р)ОЧС работает со своими операциями
- **Интеграция с КОНТУР** — отправка зон в полевую систему координации (ATAK + Meshtastic)
- **Архив завершённых поисков** — факт vs прогноз (дистанция, направление, место находки) для калибровки зонального скоринга
- **Администрирование** — пользователи по иерархии МЧС, журнал аудита, статистика
### Методическая основа
Расчёт радиуса основан на статистических таблицах ПСР (поиск и спасение, экстремум-методика): базовая скорость смещения по среднему лесу (НормС) умножается на коэффициенты возраста, диагноза, рельефа, погоды, времени суток, транспорта. Скоринг зон — взвешенная сумма факторов рельефа (лес, вода, дороги, НП) по секторам вокруг ТНП.
### Домен
МЧС осуществляет поиски **только в природных экосистемах** — не в городах. Город учтён в коэффициентах рельефа, но приоритетные зоны строятся для природной среды.
---
## 2. Ключевая политика: полностью закрытый контур
**Все данные о поисках (включая ПДн детей) не покидают контур организации.**
- **ИИ/LLM удалён из проекта полностью** (решение руководства): анализ детерминированный, `backend/services/claude_service.py` и любые облачные API исключены. В `docker-compose` и `.env` НЕТ никаких API-ключей внешних сервисов
- **Расчёт локальный**: вся математика в `services/*.py` (Python), выполняется на сервере за миллисекунды
- **Карты — из локальной OSM**: дамп Geofabrik (беларусь-latest.osm.pbf, ~333 МБ) импортирован в PostGIS внутри организации; бэкенд не ходит в Overpass/интернет (fallback на Overpass остаётся только на случай пустых OSM-таблиц)
- **Фронтенд** тянет OSM-тайлы и иконки Leaflet с CDN — для полностью offline-контура требуется локальный tile-сервер (в планах)
Тест-страж: `backend/tests/test_rules_analysis.py::TestNoLLM` — падает, если в код возвращается внешний ИИ.
---
## 3. Архитектура
```
┌───────────────────────────────────────────────────┐
│ Браузер пользователя │
│ (Chrome / Firefox / Edge — любая ОС) │
└──────────────────────┬────────────────────────────┘
│ HTTP
┌──────────────────────▼────────────────────────────┐
│ vector-frontend (React 18, CRA, порт 3000) │
│ Форма карточки · карта Leaflet · дашборд · админка│
└──────────────────────┬────────────────────────────┘
│ REST JSON :8000
┌──────────────────────▼────────────────────────────┐
│ vector-backend (FastAPI, порт 8000) │
│ ┌──────────────────────────────────────────────┐ │
│ │ Роутеры: auth, cases, analyze, operations, │ │
│ │ admin, admin_users, closed_cases, contour, │ │
│ │ water, geocode, stats, health │ │
│ └──────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────┐ │
│ │ Services (математика, без БД/HTTP): │ │
│ │ search_engine (модель), distance_service │ │
│ │ (радиус), scoring_service (сектора), │ │
│ │ rules_analysis (правила), psychotype, │ │
│ │ geo_service → osm_local (PostGIS) │ │
│ └──────────────────────────────────────────────┘ │
└──────────────────────┬────────────────────────────┘
│ SQLAlchemy / psycopg2
┌──────────────────────▼────────────────────────────┐
│ vector-postgres (PostgreSQL 16 + PostGIS 3.6) │
│ БД vector_mchs: кейсы, операции, юниты, аудит, │
│ OSM (planet_osm_*: 1 млн дорог, 192 тыс. лесов) │
└───────────────────────────────────────────────────┘
│ (опционально, outbound)
┌──────────────────────▼────────────────────────────┐
│ КОНТУР (CT130, полевая координация ATAK) │
│ POST /api/v1/vector/zones — приоритетные зоны │
└───────────────────────────────────────────────────┘
```
### Принципы архитектуры
- **Чистая математика**: `services/*.py` не знают ни о БД, ни об HTTP — только входные словари на выходе модели. Тонкие роутеры-обёртки в `backend/routers/`
- **Контракт /analyze**: `zone.forest_pct` — доля 0..1 (не проценты!), дистанции — км (в PostGIS SRID 3857 раздувание мерка: real = mercator × cos(lat))
- **Анализ воспроизводим**: тот же вход — тот же выход; прогон модели сохраняется в `analysis_log` кейса и сравнивается с фактом в архиве
---
## 4. Стек технологий
| Слой | Технология | Версия | Назначение |
|------|-----------|--------|-----------|
| Бэкенд | FastAPI | 0.115 | REST API |
| ORM | SQLAlchemy 2.0 + psycopg2 | | БД + миграции Alembic 1.14 |
| БД | PostgreSQL 16 + PostGIS 3.6 | | Данные + гео (PostGIS) |
| OSM | osm2pgsql 2.1 | | Импорт дамп OSM → planet_osm_* |
| Auth | python-jose + passlib | | JWT + bcrypt, server-side сессии |
| Фронт | React 18 (CRA) + react-leaflet | | SPA |
| Карта | Leaflet 1.9 + OSM-тайлы | | Отображение зон |
| Контейнеры | Docker Compose | | 4 сервиса |
Полный список зависимостей — `backend/requirements.txt` и `frontend/package.json`.
---
## 5. Структура репозитория
```
vector/
├── backend/ # FastAPI-приложение
│ ├── main.py # Сборка приложения (12 роутеров)
│ ├── models.py # 21 таблица (SQLAlchemy)
│ ├── schemas.py # Pydantic-схемы
│ ├── database.py # Репозиторий кейсов + статистика
│ ├── audit.py # Журнал аудита + гео-скоуп
│ ├── rbac.py # Роли/права/политика безопасности
│ ├── alembic/ # Миграции (006…009)
│ ├── seed_users.py # Сид первых пользователей
│ ├── seed_units.py # Сид подразделений (РЦУ РЧС → ОУМЧС → Г(Р)ОЧС, 142 юнита)
│ ├── routers/ # 12 модулей API (см. раздел 8)
│ ├── services/ # Адаптеры расчёта
│ └── tests/ # 231 тест (pytest)
├── services/ # Математика (чистые функции)
│ ├── search_engine.py # SearchInput/SearchModel — ядро расчёта
│ ├── distance_service.py # Максимальный радиус (КМЧ × коэффициенты)
│ ├── scoring_service.py # Взвешенный скоринг секторов
│ ├── rules_analysis.py # Правила: срочность, действия, поведение
│ ├── psychotype_service.py # Психотипирование (опрос)
│ ├── geo_service.py # Геоданные секторов (лес/вода/дороги/НП)
│ ├── osm_local.py # Локальный PostGIS-провайдер OSM
│ └── recommendation_service.py
├── frontend/ # React SPA
│ └── src/
│ ├── App.js # Роутинг (/dashboard, /desktop, /users, /admin)
│ ├── constants.js # Единые справочники (место находки, кто нашёл, румбы)
│ ├── api/client.js # apiFetch/apiJson — Bearer + 401-перехват
│ ├── components/ # CaseForm (5 шагов), SearchMap, ProtectedRoute
│ └── pages/ # Dashboard, DesktopSARPage, analysis/, AdminDashboard,
│ # UsersAdmin, ClosedCases, Login
├── scripts/ # Развёртывание и живые проверки
│ ├── b16-import.sh # Импорт OSM-дампа в PostGIS
│ ├── e2e-*.sh # e2e-сценарии
│ ├── eN-live-check.sh # Живые проверки этапов E1–E4
│ └── prod-stamp-backfill.sql
├── docker-compose.yml # 4 сервиса: postgres, adminer, backend, frontend
├── .env.example # Шаблон окружения (без внешних ключей)
├── SETUP_GUIDE.md # Развёртывание на серверах МЧС
├── vector_tasks.md # Живой план работ (B1…B21+)
└── README.md # Этот документ
```
---
## 6. База данных
**PostgreSQL 16 + PostGIS 3.6**, БД `vector_mchs`. Схема управления — Alembic (`backend/alembic/versions/`), актуальная ревизия **009_e3_operations**.
### Основные таблицы
| Таблица | Назначение |
|---------|-----------|
| `cases` | Карточки поисков: субъект, обстоятельства, среда, ТНП, исход |
| `analysis_log` | JSONB-лог прогонов анализа (аудит расчётов) |
| `search_models` | Слой 4: сохранённые матмодели по кейсам (GeoJSON-зоны) |
| `search_teams`, `field_observations`, `areas_checked`, `found_events` | Оперативные слои (состав групп, наблюдения, проверенные квадраты, находки) |
| `reference_priors` | Слой 1: справочные приоритеты |
| `users`, `mchs_units` | Пользователи; иерархия РЦУ РЧС → 6 ОУМЧС → 135 Г(Р)ОЧС |
| `roles`, `permissions`, `role_permissions`, `user_roles` | RBAC: 4 роли, 9 прав, матрица связей |
| `sessions`, `auth_events` | Server-side сессии (sha256-токены), журнал входов |
| `security_settings` | Политика безопасности (10 параметров) |
| `search_operations` | Поисковые операции (статусная машина, привязка к кейсу и КОНТУРу) |
| `audit_events`, `audit_changes` | Неизменяемый журнал аудита, field-level изменения (ретенция 90 дней) |
| `planet_osm_*` | Импорт OSM Беларуси (osm2pgsql, SRID 4326/3857): дороги, леса, вода, НП |
### Политика безопасности (`security_settings`, меняется в админке)
| Параметр | Значение |
|----------|----------|
| Минимальная длина пароля | 8 |
| Сложность пароля | требуются буквы+цифры |
| Срок действия пароля | 90 дней |
| История паролей | 5 (нельзя переиспользовать) |
| Блокировка после неудачных входов | 5 (на 15 минут) |
| Тайм-аут сессии / неактивности | 24 ч / 60 мин |
| Макс. параллельных сессий | 3 (старые отзываются) |
| Ретенция журнала аудита | 90 дней |
---
## 7. Математическая модель расчёта
Ядро — `services/search_engine.py`: `SearchInput` → `SearchModel` (чистая функция, без БД/HTTP).
### Состав расчёта
1. **Максимальный радиус** (`distance_service.py`): НормС (скорость смещения по среднему лесу, км/ч) × коэффициенты возраста / диагноза / рельефа / погоды / времени суток / транспорта, с учётом усталости. Контрольные точки: подросток 14 л, 3 ч, лес = 5.1 км; велосипедист 8 л, 2 ч = 10.8 км
2. **Коэффициенты рельефа** (`terrain_map`): лес/поле/луг/город/неизвестно = 1.0; густой лес = 0.5; болото = 0.4; горы/овраги = 0.6; дорога/тропа = 0.8
3. **Сектора направлений** (`scoring_service.py`): 8 секторов по 45° вокруг ТНП; каждый сектор оценивается по составу рельефа из локальной OSM (лес — доля 0..1, вода/НП — расстояние в км), приоритетные подсвечиваются на карте
4. **Психотип** (`psychotype_service.py`): опрос из формы → доминантный / гармоничный / тревожный / интроверт → модификаторы поведения и рекомендаций
5. **Правила** (`rules_analysis.py`): срочность (critical/high/elevated/normal), критические действия, прогноз поведения по профилям (не_умеет_плавать ×3.0 к водоёмам и т.п.), тактические рекомендации («проверить водоёмы», не «перекрыть»)
6. **Профили, не покрытые моделью** (ДЦП, слабое зрение/слух) — честно помечаются `unmodeled_profiles`, не искажают расчёт
**Коэффициенты меняются только по явному решению руководства** — молча таблицы не трогать.
---
## 7. OSM-геослой (PostGIS)
- Импорт: дамп [Geofabrik](https://download.geofabrik.de/europe/belarus-latest.osm.pbf) (~333 МБ) → `scripts/b16-import.sh` (osm2pgsql --slim, ~4,5 мин, RAM 2 ГБ)
- Содержимое: 1 010 507 дорог, 192 374 леса, 81 772 воды, 2 731 НП
- Провайдер `services/osm_local.py` читает `planet_osm_*`; `geo_service.py` переключается на Overpass только если таблицы пусты
- Полный `/analyze` на локальных данных: ~10 мс (см. `scripts/e2e-b16-timing.sh`)
- Обновление дампа — по решению (раз в квартал / заморозить)
---
## 8. Бэкенд (FastAPI) — структура и API
`backend/main.py` собирает 12 роутеров. Авторизация — Bearer JWT (form-urlencoded логин, OAuth2PasswordRequestForm).
| Префикс | Модуль | Назначение |
|---------|--------|-----------|
| `/api/v1/health` | health.py | Liveness |
| `/api/v1/auth` | auth.py | Логин/логаут/me/смена пароля, блокировки |
| `/api/v1/cases` | cases.py | CRUD карточек поисков |
| `/api/v1/analyze` | analyze.py | Матрасчёт зон (по payload или case_id) |
| `/api/v1/operations` | operations.py | Операции мультипоиска (CRUD, статусная машина, /summary), завершение поиска |
| `/api/v1/operations/{id}/send-to-contour` | contour.py | Отправка зон в КОНТУР; GET areas-checked (прокси) |
| `/api/v1/admin` | admin.py | Список/редактирование кейсов, дашборд-метрики |
| `/api/v1/admin/users` | admin_users.py | Пользователи (создание/роли/юниты/блокировка/сброс пароля) + журнал аудита |
| `/api/v1/closed-cases` | closed_cases.py | Архив завершённых поисков (ручной ввод + прогон модели) |
| `/api/v1/water/{case_id}` | water.py | Вода/болота (полигоны), ж/д (линии) вокруг ТНП |
| `/api/v1/geocode` | geocode.py | Прокси Nominatim (формат «пункт, район, адрес») |
| `/api/v1/stats` | stats.py | Тепловая карта, агрегаты |
Swagger: `http://<сервер>:8000/docs`.
**Синхронизация закрытия**: кейс закрывается через ЛЮБОЙ из путей (`PATCH /admin/cases` или `POST /operations/{id}/complete`) — активная операция кейса автоматически завершается (`completed` + `closed_at`).
---
## 9. Фронтенд (React)
SPA на react-scripts (CRA). Роутинг:
| Путь | Страница |
|------|----------|
| `/dashboard` | Главная: «Активные поиски» (счётчики, карточки операций, «+ Новый поиск», «Пользователи») |
| `/desktop` | Рабочее пространство: форма карточки (5 шагов) + карта + результат анализа |
| `/analysis/:case_id` | Результат анализа: карта зон, КОНТУР-панель, «Завершить поиск» |
| `/users` | Админка пользователей + вкладка «Аудит» |
| `/admin` | Администрирование: Кейсы / Операции / Завершённые поиски |
Компоненты:
- **CaseForm** — 5 шагов: субъект → обстоятельства → среда → координаты (ТНП + геокодирование) → ресурсы; после сохранения автоматически создаётся поисковая операция
- **SearchMap** — концентрические круги (0.5R/0.75R/R) + подсветка приоритетных направлений 45°-секторами (палитра ЦОУ: #ff4d00 / #ff9f1a / #ffd166)
- **Dashboard / UsersAdmin / AdminDashboard** — VCL-density, тёмная тема (#0d1117 / #161b22 / #30363d / #e6edf3)
Единые справочники исхода — `frontend/src/constants.js` (тип места находки, кто нашёл, 8 румбов) — используются во всех точках ввода исхода.
---
## 10. Аутентификация, роли и подразделения (RBAC)
### Иерархия подразделений
РЦУ РЧС (республиканский) → 6 областных ОУМЧС → 135 Г(Р)ОЧС/ПАСО. Справочник — идемпотентный сид `backend/seed_units.py` (источник: справочник подразделений РВС).
### Роли
| Роль | Права | Скоуп видимости |
|------|-------|----------------|
| **admin** (РЦУ РЧС) | Все 9 прав | Все операции и пользователи республики |
| **coordinator** (ОУМЧС) | view/create/update/export/manage_users/view_audit | Своё ОУМЧС + подчинённые Г(Р)ОЧС |
| **operator** (Г(Р)ОЧС) | view/create/update | Свои поиски |
| **observer** | view | Только просмотр |
- Управление пользователями (`manage_users`): РЦУ РЧС — все; ОУМЧС — только своё поддерево (кросс-областные операции отбиваются 403 на бэкенде)
- Созданный пользователь обязан сменить пароль при первом входе (`must_change_password`)
- Сессии server-side: JWT несёт идентификатор, в БД — sha256-хэш; сброс пароля отзывает все сессии
---
## 11. Мультипоиск и операции
`search_operations` — надстройка над кейсами для одновременной работы с несколькими поисками:
- Одна операция на карточку (case_id unique)
- **Статусная машина**: planned → active ⇄ paused → completed → archived (недопустимые переходы → 400)
- Авто-создание операции при сохранении карточки; дашборд показывает активные
- `POST /operations/{id}/complete` — завершение поиска: исход (найден живым/погибшим, дистанция, направление, кто нашёл) → кейс в архив + детерминированный прогон матмодели → сравнение «прогноз vs факт» (accuracy_note)
- `GET /operations/summary` — счётчики для дашборда (активные / всего / завершено за 24 ч)
---
## 12. Интеграция с КОНТУР (отправка зон)
КОНТУР — система полевой координации (ATAK + Meshtastic). ВЕКТОР отдаёт приоритетные зоны (outbound):
1. В операции задаётся `contour_operation_id` (UUID операции в КОНТУРе)
2. `POST /api/v1/operations/{id}/send-to-contour` строит `SearchZones[]` (GeoJSON-полигоны секторов ±22.5°, `zone_id = vec:<НАПР>:<дист>m`, probability по приоритету) и отправляет на `{CONTOUR_API_URL}/api/v1/vector/zones?operation_id=…` с `Bearer CONTOUR_TOKEN`
3. Каждый шаг аудируется (`contour_send_ok` / `contour_send_failed`); ошибка КОНТУРа → 502
4. `GET /api/v1/operations/{id}/areas-checked` — прокси проверенных полевых квадратов (inbound, B17)
Переменные окружения: `CONTOUR_API_URL` (по умолчанию `http://192.168.0.130:8000`), `CONTOUR_TOKEN`.
---
## 13. Аудит
Неизменяемый журнал (append-only):
- `audit_events`: кто, что, когда, IP, user-agent, тип события (login/lockout/user_*/operation_*/contour_send_*/case_closed)
- `audit_changes`: field-level `старое → новое` по каждому изменённому полю
- Ретенция 90 дней (фильтруется при чтении из `security_settings`)
- Доступ: право `view_audit` — вкладка «Аудит» в админке `/users` с фильтром по типу и пагинацией
---
## 15. Что готово и что в планах
### Реализовано
- Форма карточки поиска (5 шагов), справочники, автоподсчёт «прошло времени»
- Детерминированный матрасчёт: радиус, сектора, поведение, срочность, рекомендации — без ИИ
- Локальный OSM-геослой в PostGIS (Беларусь), /analyze ~10 мс, без внешних вызовов
- Карта: концентрические круги + подсветка направлений (дизайн согласованный)
- РБАК: иерархия РЦУ РЧС → ОУМЧС → Г(Р)ОЧС (142 юнита), 4 роли / 9 прав, блокировки, сессии
- Мультипоиск: операции, статусная машина, дашборд «Активные поиски»
- Завершение поиска с внесением исхода, архив завершённых с «прогноз vs факт»
- Аудит 90 дней с field-level деталями
- Интеграция с КОНТУР: отправка зон (контракт B20)
- Журнал аудита пользователей: входы, изменения, отправки
- 231 автотест (pytest), 5 skipped
### В планах
- **E5 (B17)** — приём полевых данных от КОНТУРа: треки групп, проверенные квадраты (areas-checked) на карте операции
- **Живая интеграция с КОНТУР** (CT130) — настройка токена и реальная отправка зон
- **Локальный tile-сервер** — для полностью offline-фронта (сейчас тайлы OSM с CDN в браузере)
- **Калибровка settlement_score** — вкладка населённых пунктов в скоринге секторов (открытый методический вопрос)
- **Калибровка зонального скоринга** по накопленному архиву «прогноз vs факт»
---
## 16. Контакты и сопровождение
- Развёртывание и эксплуатация: см. [SETUP_GUIDE.md](SETUP_GUIDE.md)
- План работ и статус этапов: `vector_tasks.md`
- API-документация: Swagger `http://<сервер>:8000/docs`
- Репозиторий: [`Sadmin/vector`](http://192.168.0.106:3000/Sadmin/vector)
Смежные системы МЧС: **РВС** («Регистрация входящих сообщений», [`Sadmin/rvs-web`](http://192.168.0.106:3000/Sadmin/rvs-web)), **КОНТУР** (полевая координация).