AAYMA
RU
Войти

AKIM — Astana City Lab

Трёхъязычный симулятор городского управления Астаной: бюджет 100, пять решений из 14 мер по 5 районам, расчёт Astana Quality of Life Score.

Доведённый продукт
Команда «Triangle» 4💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Triangle
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Доведённый продукт

Задача кейса: «Аким на 5 часов»: городской симулятор, распределяющий бюджет по 5 направлениям и 5 районам

Суть

Трёхъязычный симулятор городского управления Астаной: бюджет 100, пять решений из 14 мер по 5 районам, расчёт Astana Quality of Life Score. Есть 3D-карта на данных OSM, AI-советник и автоматическая презентация по району.

Как устроено

Детерминированный движок реализует правила организаторов: горизонт 8 кварталов с лагами, несовместимости, синергии, Score = 0.7·AVG + 0.3·MIN − K. Вклад мер считается точными значениями Шепли по 120 порядкам. Рекомендации ищут лучшую одиночную замену меры, а полный перебор 694 395 сценариев находит глобальный оптимум и сохраняет его сертификат с SHA-256. AI-советник на OpenAI Responses API с tool calling отвечает на «что если» и предлагает распределение бюджета, движок проверяет план, применяет его пользователь. Фронт: React, MapLibre и Three.js. Бэкенд: Node с SQLite локально и Worker с D1 в облаке, аккаунты с ролями.

Ключевые решения

  • значения Шепли
  • полный перебор оптимума
  • tool calling
  • OpenAI Responses API
  • MapLibre 3D по OSM
  • Three.js-сцены кварталов

Метрики

Базовый Score 52.55768; глобальный оптимум 57.236735 (стоимость 98) среди 694 395 допустимых сценариев; 43 теста

Особенности

Глобальный оптимум подтверждён сертификатом и независимым скриптом верификации. Вклады мер — точные значения Шепли. Реальная 3D-геометрия OSM (5 858 объектов). Для каждого района автоматически собирается презентация из 6 слайдов. AI только объясняет и предлагает, все числа считает движок.

Стек

React 19 · React Router · MapLibre · Three.js · Leaflet · Node.js · SQLite · Cloudflare Workers · D1 · Drizzle · Vite

Модели

OpenAI Responses API


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-314bbb86-triangle.

README

README.md

AKIM — Astana City Lab

«Аким на 5 часов» / «5 сағатқа әкім» / Mayor for 5 Hours
Triangle · Astana Innovations · Hackathon track 12

Интерактивный симулятор городского управления: реальные границы районов Астаны, 100 единиц бюджета, пять решений и объяснимый Astana Quality of Life Score. Интерфейс, каталог инициатив и AI-отчёты доступны на қазақша / русском / English.

Сайт: Открыть AKIM City Lab

Быстрый запуск

Требуется Node.js 22.12+ и npm. Команды из корня репозитория:

npm ci
cp .env.example .env
npm run accounts:create
npm run dev

Windows PowerShell: Copy-Item .env.example .env. Откройте http://127.0.0.1:3100. Команда accounts:create создаёт два аккаунта: аким и управленец. Логины и случайные пароли находятся в игнорируемом .data/demo-credentials.json; передайте их только участникам команды. Повторный запуск меняет пароли. Хеши записываются в серверный AUTH_ACCOUNTS в .env. Заполните OPENAI_API_KEY в .env для реального AI. Без ключа доступно честно помеченное объяснение по правилам; расчёт и сохранение продолжают работать. Ключ считывается только сервером. .env, SQLite-файлы и сборки исключены из Git.

npm test                 # 43 проверки модели, API, аккаунтов и SQLite
npm run build           # React + Worker + миграции базы
npm start               # локально обслуживать готовую сборку на :3100
npm run db:generate     # после изменения db/schema.ts
npm run optimize        # полный перебор, обновляет сертификат оптимума
npm run verify:optimum  # независимая полная проверка через основной движок (~30 с)

node:sqlite в Node 22.12 выводит предупреждение experimental — это ожидаемо. Локальный сервер слушает только loopback. Для размещения используется Sites с Worker и D1; это отдельный адаптер того же API, не раздача локального компьютера.

Демонстрация за 3 минуты

  1. Откройте публичную карту: реальные здания, дороги, парки и река OSM в 3D. Выберите район и приблизьте его фрагмент. Языки: қазақша / русский / English.
  2. Войдите по выданному демо-аккаунту акима или управленца. У гостя — просмотр.
  3. В рабочем пространстве Нуры добавьте M7 (школа) и M3 (транспорт). Бюджет этих двух мер — 54. Переключите «До / После»: S1 38→48, T1 55→63, индекс Нуры 49.18→52.30. Школа появляется после предусмотренного лага.
  4. В той же странице откройте «Презентация»: шесть слайдов только об этом районе, снимки текущих сцен Q0/Q8, десять показателей, график кварталов, местные и общегородские расходы, риски и задачи следующего квартала. Скачайте автономный HTML или используйте печать PDF.
  5. Для официального городского Score завершите пять решений. Можно поручить AI составить план с пустого черновика: движок проверит бюджет, модель объяснит выбор; применение требует отдельного нажатия пользователя.
  6. Сохраните и сравните сценарии. После выхода и повторного входа черновик восстанавливается из базы. Публикация в рейтинге и общая ссылка — явные действия.

Что реализовано

  • Страницы сводки, карты, районного кабинета, планирования, AI-советника, личных сценариев, результатов, сравнения, рейтинга, методики и входа.
  • MapLibre: белые объёмные здания на реальных OSM-контурах, дороги, парки, водоёмы; фрагменты пяти районов и режим границ шести современных районов. При отсутствии WebGL — резервная 2D-карта Leaflet.
  • Пять разных Three.js-кварталов: набережная Есиля, плотные кварталы Алматы, зелёная Сарыарка, железнодорожный Байконур, новая застройка Нуры. Машины, пешеходы, дети и объекты мер меняются вместе с выбранным планом.
  • Планирование, анимация, показатели и презентация объединены по району.
  • Исходные 5 районов, 10 показателей, 14 мероприятий, общий бюджет 100, серверный контроль ограничений, точный Шепли, оптимум и квартальные графики.
  • OpenAI Responses API, tool calling для «что если» и распределения бюджета, районные отчёты, кеш, лимиты, явно обозначенный режим без AI.
  • Два настоящих аккаунта с ролями из базы, вход/выход, отзываемые сессии. Только аким и управленец могут менять планы, сохранять и использовать AI.
  • SQLite локально / D1 в облаке: аккаунты, сессии, черновики, сценарии, AI-отчёты и квоты. Проверка владельца на сервере, контроль ревизий черновика.
  • Три языка, мобильная компоновка, состояния загрузки и ошибок, пауза анимации и поддержка prefers-reduced-motion.

Точная модель организаторов

Использованы подробные правила приложенного датасета: ровно 5 разных мер, не более 2 из одного направления. Не требуется по одной мере на каждое направление — это существенная деталь подробного ТЗ. Все пять направлений доступны.

  1. Начальный бюджет — 100; неиспользованный остаток не даёт бонус.
  2. Горизонт — 8 кварталов. Реализованный эффект: полный эффект × (8 − лаг) / 8.
  3. Городские меры влияют на все пять районов; локальным нужен район.
  4. M1 + M3 несовместимы в любом сочетании районов. M4 + M7 и M5 + M13 несовместимы только в одном районе.
  5. Синергии M1+M2, M5+M6, M10+M12 применяются в районе локальной меры и не уменьшаются лагом. Показатели ограничены диапазоном 0–100.
  6. Балл района = сумма десяти показателей, умноженных на их веса.
  7. AVG — среднее районов с учётом долей населения; MIN — слабейший район.
  8. K — число показателей строго ниже 40 во всех районах.
Astana Quality of Life Score = 0.7 × AVG + 0.3 × MIN − K
Базовый Score              = 52.55768
AVG                        = 56.8624
MIN                        = 49.18 (Нұра)
K                          = 2

Веса, исходные значения, эффекты, лаги и синергии открыты в shared/data.mjs и на странице «Методика». Все 50 исходных показателей одинаковы для игроков. Рекомендации перебирают одну замену и возвращают до трёх лучших допустимых улучшений. Отдельная карточка показывает глобальный оптимум конечной модели. Вклад исключением одной меры сохранён отдельно и не является аддитивным. Точные вклады Шепли усредняют маржинальный эффект по всем 120 порядкам добавления пяти мер через 32 подмножества. Их сумма равна изменению Score.

Полный оптимум

scripts/optimize.mjs перебирает возрастающие наборы пяти мер и все назначения районов. Проверены 694 395 допустимых уникальных сценариев. Единственный максимум: 57.236735, стоимость 98:

M2 — весь город
M3 — Нура
M8 — Нура
M9 — Нура
M14 — весь город

Сертификат shared/optimum-certificate.json хранит точный целочисленный Score, число вариантов, SHA-256 исходных данных и семантический отпечаток модели. Независимый scripts/verify-optimum.mjs повторяет весь перебор через обычные validate/calculate. При изменении данных сертификат нужно пересоздать. Этот максимум относится к заданной учебной модели, а не к реальному городу.

Время, визуализация и презентация

Для конца квартала q: эффект × max(0, q − lag) / 8. Фиксированный бонус синергии включается в max(lagA, lagB) + 1. Это явно обозначенное допущение для промежуточных кварталов. Q0 совпадает с исходными показателями, Q8 точно совпадает с итоговой формулой организаторов. Каждый квартал пересчитываются пороги, слабейший район и Score: график может снижаться. Весь бюджет считается выделенным в начале плана, отдельного денежного потока нет.

«До и после» показывает условный квартал, а не реальные здания. Количество машин и людей в 3D-сцене декоративное. При улучшении T1 поток становится визуально свободнее, M7 добавляет школьный корпус. Другие меры добавляют свои условные объекты. Сцена не обещает реального числа мест или автомобилей. Все численные показатели рядом рассчитаны движком.

Презентация строится для выбранного района из тех же решений и движка. Она содержит шесть слайдов: снимки Q0/Q8, применимые меры и расходы, изменения десяти показателей, квартальный индекс района, сильные стороны/риски, задачи следующего квартала. AI-анализ запрашивается отдельно по этому району. Частичный план помечен как предварительный; официальный городской Score требует ровно пять решений. Общегородские расходы не выдаются за бюджет района. HTML содержит обе картинки и диаграммы внутри файла и работает без интернета. PDF создаётся штатной печатью браузера. Это HTML/PDF, не файл PowerPoint.

География и источник данных

На карте шесть районов OSM; учебный датасет содержит пять. Сарайшық показан нейтральным и исключён из расчёта. Границы не являются кадастровой картой, учебные показатели — не реальная статистика города.

Белая 3D-модель использует 5 858 объектов OSM: 1 281 здание, 137 частей зданий, дороги, парки и воду. Загружены центр у Байтерека и выбранные фрагменты остальных районов, не вся застройка города. Высоты взяты из OSM, оценены по этажности × 3 м либо заданы резервными 8 м; происхождение помечено в данных. Эта географическая карта показывает существующую застройку. Изменения мер показывает отдельная связанная с планом Three.js-сцена внутри кабинета района: для мероприятий нет точных реальных координат в датасете организаторов.

Источники, даты и ODbL: границы, городская геометрия, машиночитаемые метаданные.

Архитектура

frontend/              React 19, React Router, MapLibre, Three.js, CSS, 3 языка
  public/              GeoJSON районов, здания/дороги OSM, иллюстрация и favicon
  src/                 страницы, карта, результаты, переводы, API-клиент
backend/
  api.mjs              серверная валидация, сценарии, ссылки, рейтинг, AI
  advisor.mjs          OpenAI Responses и объяснение по правилам
  what-if.mjs          tools, проверенные альтернативы и ограниченный цикл агента
  session.mjs          аккаунты, хеши паролей, серверные сессии и вход/выход
  database.mjs         параметризованные запросы и атомарные квоты
  sqlite.mjs           SQLite и применение миграций локально
  local.mjs            Node HTTP + Vite / production assets
  worker.mjs           Cloudflare Worker + сессии + assets
shared/                данные, модель, Шепли, проекции и сертификат оптимума
db/schema.ts           схема Drizzle
drizzle/               сгенерированные SQL-миграции и метаданные
tests/                 node:test, изолированные базы, без платных API-вызовов
scripts/build.mjs      единая сборка клиента, сервера и миграций
.openai/hosting.json   идентификатор сайта и логическая привязка D1

Клиент и сервер используют одну модель. Предварительный расчёт выполняется в браузере, итоговый повторяется сервером. Клиентский score не принимается. База хранит решения, версию датасета и вычисленный результат для рейтинга; при чтении показатели пересчитываются из решений.

API

МетодПутьДоступ / назначение
GET/api/configПублично: правила, настройка AI, текущий аккаунт
POST/api/auth/loginEmail и пароль → сессия в HttpOnly cookie
POST/api/auth/logoutОтзыв текущей сессии и очистка cookie
GET / PUT/api/draftАким/управленец: личный черновик с ревизией
POST/api/simulateАким/управленец: проверенный результат пяти решений
POST/api/analyzeАким/управленец: decisions, locale, необязательный districtId
POST/api/what-ifАким/управленец: объяснение и журнал проверенных tools
GET / POST/api/scenariosСвои сценарии / сохранение
GET / DELETE/api/scenarios/:idТолько владелец
POST/api/scenarios/:id/shareВладелец создаёт ссылку для чтения
POST/api/scenarios/:id/publishВладелец явно публикует в рейтинг
GET/api/shared/:tokenПубличное чтение по непрогнозируемому UUID
GET/api/leaderboardПубличные результаты текущей версии модели

Доступ и хранение

  • Сайт открыт по ссылке для просмотра. Изменение планов, личные сценарии и AI требуют одного из двух выданных аккаунтов. ChatGPT-вход не используется.
  • Роль загружается из таблицы accounts; выбора роли для получения прав нет. Это демо-аккаунты конкурса, а не подтверждение реальной городской должности.
  • AUTH_ACCOUNTS — серверный секрет с email, ролью, солью и хешем пароля. npm run accounts:create создаёт случайные пароли и PBKDF2-SHA256 с 100 000 итераций и отдельной солью. При размещении перенесите значение AUTH_ACCOUNTS в секреты сервера. Пароли и ключ OpenAI не коммитятся.
  • Сессия: случайный непрозрачный токен, в базе только SHA-256, срок 8 часов, HttpOnly / SameSite=Strict / Secure на HTTPS. Выход отзывает токен в базе. Истёкшие сессии и изменённые пароли не принимаются. Старые гостевые cookie и заголовки платформы не дают доступа к аккаунту.
  • Лимиты входа: 10 попыток на email и 30 на IP за 15 минут. Origin и Sec-Fetch-Site проверяются до изменяющего запроса.
  • Черновики хранятся в базе отдельно по аккаунтам. Ревизия предотвращает потерю изменений при одновременной записи. Заголовок ожидаемого аккаунта не позволяет старой вкладке записать план под чужой новой сессией.
  • LocalStorage хранит язык и выбранный район; личный черновик хранится на сервере. Локальная база — .data/akim.sqlite, в облаке — D1 с SQL-миграциями. Шесть таблиц: accounts, auth_sessions, drafts, scenarios, analyses, usage.
  • До 100 сценариев на владельца; лимит атомарный, SQL параметризован. Публикация раскрывает название команды, сценарий и решения. Удаление сценария удаляет его из рейтинга и делает общую ссылку недоступной.
  • Старые личные гостевые сценарии не присваиваются новым аккаунтам автоматически.

AI

OPENAI_MODEL=gpt-4.1-mini; сервер передаёт только синтетические показатели и решения, без имён пользователей и команд. Ключ не попадает в клиент и Git. store:false, JSON Schema для отчёта, таймаут 25 секунд. Кеш привязан к решениям, выбранному району, языку, версии модели расчёта, версии промпта и имени AI-модели. До 3 новых запросов в минуту на аккаунт, 6/мин по доверенному cf-connecting-ip, когда он доступен, и общий лимит по умолчанию 60/день (AI_DAILY_LIMIT). Общий лимит действует даже при пересоздании cookie. Проверка Origin выполняется до обработки изменяющего запроса. При отсутствии ключа, превышении лимита или ошибке AI результат остаётся доступным с объяснением по правилам и явной отметкой режима. AI может неточно сформулировать вывод: численные карточки и проверенные альтернативы всегда берутся из детерминированного движка.

AI распределяет бюджет через инструменты: current_scenario, evaluate_replacement, evaluate_scenario, best_replacements, global_optimum. Первый вызов модели обязан вызвать вычислительный инструмент. Backend использует только этот список, повторно валидирует каждый план и возвращает реальные числа. Максимум три обращения к модели и три tool calls на диалоговый запрос, общий таймаут 45 секунд. Один лимитируемый запрос чата может включать до трёх обращений к OpenAI. Ни один инструмент не сохраняет, не публикует и не применяет сценарий. При недоступности AI отображается явная ошибка режима, проверенные вычисления остаются доступны. Текст пользователя и выбранные решения передаются OpenAI.

Источники и роль новостей

Подход «LLM вызывает оптимизатор и объясняет результат» вдохновлён Microsoft OptiGuide. Формат tools следует OpenAI function calling. Многомерность качества жизни концептуально сопоставима с OECD Well-being Data Monitor и UN-Habitat CPI. Наша формула задана организаторами, она не воспроизводит методики OECD/CPI.

Реальный контекст можно сверять с социально-экономическим паспортом Астаны за январь 2026. Справочные ссылки просмотрены 23.09.2026. Автоматического чтения новостей в AI сейчас нет. В соревновательном режиме новости не меняют показатели и веса. Дальнейшая интеграция требует отдельного режима с датой, источником и версией данных, иначе стартовые условия команд перестанут быть одинаковыми.

Работа команды из трёх человек

git clone https://github.com/BAITC-Hacks/hack-314bbb86-triangle.git
cd hack-314bbb86-triangle
git switch -c feature/your-task
npm ci

Разделение: участник 1 — frontend/; участник 2 — backend/, db/, drizzle/; участник 3 — модель shared/, тесты, документация и презентация. Общие контракты API и формулу обсуждать перед изменениями. Обычный процесс: commit → push ветки → pull request → review → merge. Запись файла на компьютере сама по себе не отправляет его в GitHub. Секреты каждому участнику передаются отдельно.

Проверка и развитие

npm test: 43 автоматические проверки. Покрыты исходная формула, пример, 100/103 единицы, 4/5/6 решений, дубль, неизвестные поля, все конфликты, лаги, синергии, отрицательные эффекты, порог 40, рекомендации, владельцы, ссылки/рейтинг, гонки запросов, сохранение после перезапуска SQLite, AI-кеш по языкам, ограничения запросов, вход/выход, отзыв сессий, роли, изоляция и ревизии черновиков, function calling, Шепли против 120 перестановок, оптимум и квартальные проекции. Реальный AI проверяется вручную, чтобы обычные тесты не тратили ключ команды.

Следующие осмысленные улучшения: приглашения участников и совместное редактирование; неожиданные события в отдельном режиме с фиксированным seed; реальные данные только с подтверждёнными источниками и новой версией модели; персона-агенты районов, граф причинных связей и персональные веса в отдельном представлении. Они не меняют честные стартовые условия текущего режима.

Қазақша

Қонақтар Астана картасы мен оқу мысалын көре алады. Өзгеріс енгізу және AI қолдану үшін әкім немесе басқарушы аккаунтымен кіріңіз. Жоспар дерекқорда сақталады. Әр ауданның өз 3D көрінісі бар: шараны таңдағанда «дейін/кейін», көрсеткіштер және сол ауданның алты слайдтық есебі бірге жаңарады. HTML жүктеу және PDF басып шығару бар. Көрсеткіштер — синтетикалық оқу деректері. Іске қосу: npm ci, .env.example → .env, npm run accounts:create, npm run dev. Демо логиндер мен құпиясөздер — .data/demo-credentials.json. API кілті серверде ғана. npm test — 43 тексеру.

English

Public visitors can explore the map and read an example. Only the two database accounts (mayor and city manager) can edit plans, save scenarios or use AI. Sign-in creates a revocable eight-hour server session; drafts persist per account. Real OSM buildings, roads, parks and water cover selected district fragments. Five distinct illustrative 3D scenes show planned changes with the same decisions, quarter projections and district-specific six-slide HTML/PDF reports. AI calls validated calculation tools; official scores remain deterministic. All statistical inputs are synthetic, not current city statistics.

Run npm ci, copy .env.example to .env, run npm run accounts:create then npm run dev. Private demo credentials are in .data/demo-credentials.json. Set OPENAI_API_KEY and AUTH_ACCOUNTS only on the server. Run npm test for 43 checks. The exact model optimum is 57.236735 at cost 98.

Звёзды
⭐ 0
Форки
0
Язык
JavaScript
Последний push
в прошлом месяце
Коммиты
12
Авторы
2
Файлы
80
Ветки
1

Авторы коммитов

taraz-08 11Ersultan 1

История коммитов

  • 2026-09-23 17:56Add files via uploadErsultan
  • 2026-09-23 18:01Видеоtaraz-08
  • 2026-09-23 17:33feat: authenticated district workspaces and real Astana 3D geometrytaraz-08
  • 2026-09-23 16:25feat: mayor workspace, verified AI planning, animated before-after and automatic presentationtaraz-08
  • 2026-09-23 15:01fix: ground AI in realized effects and document completed verificationtaraz-08
  • 2026-09-23 14:53feat: build multilingual Astana City Lab with real maps, API and databasetaraz-08
  • 2026-09-23 13:50docs: mark implementation and GitHub verification completetaraz-08
  • 2026-09-23 13:49feat: build Akim city simulator with verified scoring, AI advisor and scenario comparisontaraz-08
Все коммиты (12)
  • 2026-09-23 12:50Delete папка тестtaraz-08
  • 2026-09-23 12:50Delete тест 111/.gitkeeptaraz-08
  • 2026-09-23 12:43Добавить папку тест 111taraz-08
  • 2026-09-23 12:23Create папка тестtaraz-08
Структура репозитория (80 файлов)
.env.example
.gitignore
.openai/hosting.json
AKIM_Urban_Simulator.pdf
PLAN.md
README.md
backend/advisor.mjs
backend/api.mjs
backend/database.mjs
backend/local.mjs
backend/session.mjs
backend/sqlite.mjs
backend/what-if.mjs
backend/worker.mjs
db/schema.ts
docs/ASTANA-URBAN-METADATA.json
docs/ASTANA-URBAN-SOURCES.md
docs/MAP-SOURCES.md
docs/VERIFICATION.md
docs/VISUAL-ASSETS.md
drizzle.config.ts
drizzle/0000_cloudy_blade.sql
drizzle/0001_accounts.sql
drizzle/meta/0000_snapshot.json
drizzle/meta/0001_snapshot.json
drizzle/meta/_journal.json
frontend/index.html
frontend/public/astana-districts.geojson
frontend/public/astana-urban.geojson
frontend/public/favicon.svg
frontend/public/images/astana-concept.jpg
frontend/src/Auth.jsx
frontend/src/CityMap.jsx
frontend/src/CityScene.jsx
frontend/src/DecisionEvidence.jsx
frontend/src/District.jsx
frontend/src/ForecastCharts.jsx
frontend/src/Future.jsx
frontend/src/Home.jsx
frontend/src/MapPage.jsx
frontend/src/Methodology.jsx
frontend/src/Presentation.jsx
frontend/src/Results.jsx
frontend/src/Scenarios.jsx
frontend/src/Simulator.jsx
frontend/src/StreetScene.jsx
frontend/src/WhatIf.jsx
frontend/src/components.jsx
frontend/src/context.jsx
frontend/src/deck.css
frontend/src/district.css
frontend/src/futures-copy.mjs
frontend/src/main.jsx
frontend/src/office-copy.mjs
frontend/src/office.css
frontend/src/quarter-tasks.mjs
frontend/src/strings.mjs
frontend/src/styles.css
frontend/src/ux-copy.mjs
frontend/src/v4-copy.mjs
frontend/src/whatif-copy.mjs
package-lock.json
package.json
scripts/build.mjs
scripts/create-demo-accounts.mjs
scripts/optimize.mjs
scripts/verify-optimum.mjs
shared/data.mjs
shared/district.mjs
shared/engine.mjs
shared/i18n-data.mjs
shared/optimum-certificate.json
shared/optimum.mjs
shared/planning.mjs
tests/advanced.test.mjs
tests/api.test.mjs
tests/auth-district-v4.test.mjs
tests/engine.test.mjs
vite.config.mjs
Видео

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.