О проекте
Команда: Datalicious
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Рабочий MVP
Задача кейса: «Аким на 5 часов»: городской симулятор, распределяющий бюджет по 5 направлениям и 5 районам
Суть
Интерактивный симулятор бюджета Астаны с 3D-картой. Игрок выбирает 5 мер из каталога M1–M14 по районам и направлениям и видит Quality of Life Score, показатели районов до и после и синергии. AI-агент ищет альтернативные планы, проверяя каждый расчётным движком.
Как устроено
Один доменный модуль TypeScript проверяет набор мер (ровно 5, бюджет ≤100, не больше двух мер одного направления, несовместимости) и детерминированно считает Score с лагами, синергиями и критическими показателями ниже 40. POST /api/analyze повторно считает результат на сервере. В режиме local объяснение строится по правилам. В режиме agent модель через OpenAI Responses API вызывает инструменты get_city_context, evaluate_scenario и compare_scenarios, а числа в отчёте формирует сервер. 3D-сцена на Three.js с роботом-гидом визуализирует план.
Ключевые решения
- deterministic simulation engine
- OpenAI function calling (tool use)
- Zod validation
- серверный пересчёт результата
- лимиты агента (6 ответов, 12 вызовов инструментов, 45 с)
Особенности
Агент не выдаёт числа сам: каждый предложенный сценарий проверяется настоящим движком через tool calling, итоговый отчёт собирается из проверенных фактов. Визуально сильная 3D-карта Астаны с роботом на IK. Есть сценарий для жюри с точными ожидаемыми значениями Score. README честно указывает, что запуск с реальной моделью ещё не подтверждён.
Стек
Next.js 16 · React 19 · TypeScript · Tailwind CSS 4 · Three.js · Zod · Vitest · Playwright · Python (скрипты геоданных) · Shapely
Модели
OpenAI (Responses API, модель через OPENAI_MODEL)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-497ca5e1-datalicious.
README
README.mdАким на 5 часов
Хакатон-проект команды Datalicious — интерактивный симулятор управления городом на примере Астаны. Пользователь распределяет 100 условных единиц бюджета между пятью решениями и видит, как меняются качество жизни и положение районов. AI-агент может искать альтернативные наборы решений, проверяя каждый настоящим расчётным движком.
Текущая объединённая версия находится в ветке
main.
Расчёт и локальное объяснение работают без OpenAI и без API-ключа.
Агент подключён к интерфейсу и проверен с подменённым провайдером; успешный запуск
с реальной моделью пока не подтверждён.
Для кого и какую проблему решает
Проект предназначен для участников хакатона, городских управленцев и всех, кто хочет исследовать компромиссы бюджетного планирования. Он показывает, почему нельзя оценивать решения только по общей стоимости или среднему улучшению: важны задержка эффекта, совместимость мер, критические показатели и положение самого слабого района.
Это учебная модель на синтетических данных, а не прогноз развития города и не рекомендация для реального распределения бюджетных средств.
Что реализовано
- Интерактивная 3D-карта с роботизированным указателем, выбором районов и демонстрацией выбранных работ. При недоступности WebGL остаётся выбор кнопками.
- Профили пяти расчётных районов, десять показателей, выделение значений ниже 40.
- Каталог M1–M14: направления, стоимость, районный/городской охват, лаг и эффекты.
- Пять слотов решений, бюджет и остаток, контроль повторов, конфликтов и лимита двух мер одного направления. Невалидный набор не получает Score.
- Детерминированный расчёт: итоговый Astana Quality of Life Score, изменение относительно базы, оценки районов и показатели до/после, критические значения, ухудшения, реализованные эффекты решений и сработавшие синергии.
- Сохранение и восстановление одного плана в
localStorageтекущего браузера. - Два явных действия: «Получить локальное объяснение» и «Запустить AI-агента». Локальный ответ подписан «Локальное объяснение — без AI».
- Загрузка, ошибки и отсутствие настроек AI, блокировка повторной отправки, отмена и игнорирование устаревших ответов при смене сценария.
- Русскоязычный адаптивный интерфейс, клавиатурное управление и поддержка
предпочтения уменьшенной анимации (
prefers-reduced-motion).
Как работает решение
- Пользователь изучает район и выбирает мероприятия. Для районной меры указывает район; городская применяется ко всем пяти расчётным районам.
- Общий доменный модуль проверяет набор: ровно пять разных мер, стоимость не выше 100, максимум две одного направления, соблюдение несовместимостей. Покрывать все пять направлений не обязательно.
- Кнопка «Запустить план» вызывает настоящий движок. После десятисекундной демонстрации, которую можно пропустить, открывается результат. Анимация не рассчитывает эффективность и не означает выполнение реальных работ.
- По отдельной кнопке UI отправляет только решения и режим в
POST /api/analyze. Сервер заново проверяет сценарий и вычисляет результат по исходному датасету: клиентские стоимость и Score не принимаются на веру. - В режиме
localсервер формирует объяснение по правилам без обращения к модели. В режимеagentмодель предлагает варианты, а сервер проверяет их движком. Ответ содержит объяснение, риски, последствия и рекомендации.
Агент использует инструменты get_city_context, evaluate_scenario и
compare_scenarios. Он выбирает меры и районы, получает результаты проверок
и может исправлять невалидные предложения. Итог ссылается только на лучший
проверенный сценарий, включая исходный; если улучшение не найдено, это явно
сообщается. Числа и текстовый отчёт формируются сервером из проверенных фактов,
а не из свободных числовых утверждений модели.
Альтернатива не заменяет план автоматически: её можно перенести вручную и пересчитать. Открытие страницы, изменение полей и обычный расчёт AI не запускают.
Технологии
- Next.js 16, App Router, React 19, TypeScript — приложение и серверный маршрут.
- Tailwind CSS 4 и CSS — оформление; Three.js — 3D-карта, робот и анимация.
- Zod 4 — проверка входных данных, конфигурации и ответов.
- Официальный OpenAI SDK 6, Responses API — серверный агент с вызовом инструментов.
Модель задаётся через
OPENAI_MODEL; фиксированной модели и модели по умолчанию нет. - Vitest, React Testing Library, Playwright, ESLint — проверки кода и интерфейса.
- npm и
package-lock.json— воспроизводимая установка зависимостей.
Recharts установлен в проекте, но графики на нём в текущем интерфейсе не реализованы. Точные версии зависимостей зафиксированы в package-lock.json. Python и Shapely нужны только для отдельных скриптов обновления геоданных, не для запуска приложения.
Архитектура
| Модуль | Ответственность |
|---|---|
src/data/dataset.ts | Типизированный датасет организаторов, каталог и параметры модели |
src/domain | Чистые валидация и расчёт; публичный simulationEngine, единая реализация правил и Score |
src/domain/types.ts | Общие контракты сценария, результата, объяснения и HTTP |
src/components/city | 3D-сцена, районные панели, выбор и сохранение плана |
src/components/simulator | Результаты расчёта, таблицы и запрос объяснения |
src/server | Локальный генератор, AI-агент, инструменты, проверка ответов и ограничения запуска |
src/app/api/analyze/route.ts | POST /api/analyze: HTTP-оболочка, повторный серверный расчёт и выбранный режим анализа |
tests/domain, e2e | Доменные и сквозные проверки; компонентные/серверные тесты расположены рядом с кодом |
UI и сервер используют один расчётный модуль. Домен не зависит от React, Next.js,
OpenAI или переменных окружения. SDK доступен только серверным модулям,
защищённым server-only; секреты в браузер не передаются.
Контракт запроса — { scenario, mode?: "local" | "agent" }, успеха —
{ ok: true, result, analysis, source }. Если mode не указан, используется
agent; для бесплатной проверки нужно явно выбрать local.
Ошибки формы дают 400, нарушения правил — 422, отсутствие настроек агента — 503,
сбой агента — 502, внутренняя ошибка — 500. Ошибки не подменяются локальным успехом.
Полный контракт и точки подключения: AI_INTEGRATION.md.
Установка и запуск
Нужны Node.js ≥22.12.0, npm и Git. База данных и ключ картографического
сервиса не требуются. В Windows PowerShell при запрете запуска .ps1
используйте npm.cmd и npx.cmd вместо npm и npx.
Запуск без OpenAI
git clone --branch main https://github.com/BAITC-Hacks/hack-497ca5e1-datalicious.git
cd hack-497ca5e1-datalicious
npm ci
npm run dev
Откройте http://localhost:3000.
Для расчёта и локального объяснения .env.local создавать не нужно.
Если репозиторий уже клонирован, сначала сохраните свою работу, затем
выполните git fetch origin, git switch main и git pull --ff-only origin main.
Если локальная история разошлась с общей, сначала согласуйте её объединение с командой.
Установка зависимостей остаётся той же: npm ci.
Необязательное подключение AI-агента
Если .env.local ещё нет, создайте его на основе .env.example.
Заполните OPENAI_API_KEY своим ключом и OPENAI_MODEL точным идентификатором
доступной вам модели. Код использует Responses API, вызов инструментов и
структурированный финальный ответ; совместимость выбранной модели нужно проверить.
Перезапустите сервер после настройки.
Не коммитьте .env.local, не присылайте ключ в чат и не используйте для него
префикс NEXT_PUBLIC_. Текущий агент допускает только endpoint
https://api.openai.com/v1; произвольный совместимый шлюз не поддержан.
Кнопка «Запустить AI-агента» может расходовать API-токены. Перед живой проверкой
согласуйте модель, тариф и допустимые расходы. Обычный HTTP-маршрут ограничивает
цикл шестью ответами модели, двенадцатью инструментальными вызовами и 45 секундами,
но не задаёт денежного потолка. Отдельная серверная функция
runLiveAgentCheck требует бюджетную политику; она не вызывается кнопкой UI
и не является готовой CLI-командой. Подробности — в
инструкции AI-интеграции.
Production-запуск локально
npm run build
npm start
Приложение использует серверный API-маршрут, поэтому для полного сценария нужен работающий Next.js-сервер, а не только статическая раздача HTML.
Сценарий проверки для жюри
Можно пройти полностью бесплатно, без настройки OpenAI.
-
Откройте приложение и выберите следующие пять мер через районные панели и фильтры направлений:
Район / охват Направление Мера Стоимость Нура Соцсфера M7 — школа + детсад 24 Нура Соцсфера M8 — центр семейного здоровья / поликлиника 20 Нура Безопасность M10 — освещение и камеры 12 Весь город Сервисы M12 — единая цифровая платформа обращений 14 Сарыарка Экология M5 — перевод частного сектора на чистое топливо 25 -
Проверьте бюджет: 95 из 100, остаток 5. Нажмите «Запустить план»; дождитесь демонстрации или нажмите «Пропустить анимацию».
-
В результате должны быть исходный Score 52,55768, итоговый 56,54307, изменение +3,98539. Критических показателей: 2 → 0. Самый слабый район — Нура с оценкой 52,9625; срабатывает синергия M10 + M12.
-
Раскройте Нуру в «Районы и показатели до / после»: S1 меняется 38 → 48, S2 — 35 → 43,75. Эти числа рассчитаны доменом, не моделью AI.
-
Нажмите «Получить локальное объяснение». Должны появиться заголовок «Локальное объяснение — без AI», итог, сильные стороны, риски, последствия и рекомендации.
-
Нажмите «Вернуться к городу», сохраните план, перезагрузите страницу и нажмите «Восстановить». Удалите одну меру: запуск неполного плана должен стать недоступен.
Это исходный пример из датасета организаторов. Отрицательные эффекты тоже учитываются: отсутствие ухудшений именно в этом примере не означает, что все мероприятия всегда улучшают каждый показатель.
Автоматические проверки
npm test
npm run lint
npm run typecheck
npm run build
npx playwright install chromium
npm run test:smoke
typecheck генерирует типы Next.js перед проверкой TypeScript. Smoke требует
предварительной сборки; Playwright сам поднимает production-сервер на
127.0.0.1:3100. Этот порт должен быть свободен. Установка Chromium нужна
один раз для окружения.
Подтверждённая проверка интеграционной версии от 23 сентября 2026: 244 теста Vitest в 17 файлах, 5 тестов Playwright, lint, typecheck и build прошли успешно. Проверяются правила и контрольные числа, компонентные состояния, серверная валидация, агентный протокол, ошибки, сохранение плана, мобильная вёрстка и работа без WebGL.
Успешный Playwright-сценарий использует настоящий сервер, движок и локальный генератор — без подмены успешного ответа. Отдельный UI-тест ошибки подменяет HTTP 500. В тестах агента провайдер подменён; платные запросы не выполняются. Эти проверки не подтверждают работу с реальным OpenAI.
Данные и интеграции
Симуляция: материалы организаторов —
Описание кейса.txt и
Датасет районов.txt.
В src/data/dataset.ts находится версия organizers-v1: пять районов,
десять показателей и четырнадцать мер. Данные синтетические, без персональной
информации. Бюджет, веса населения, эффекты, лаги, конфликты и синергии заданы
этим датасетом. Горизонт расчёта — восемь кварталов; Score учитывает средний
результат, самый слабый район и критические значения строго ниже 40.
Подробная формула и правила — в DATASET.md, реализация — в домене.
Карта: локальный снимок OpenStreetMap от 23.09.2026 в
src/components/city/geodata/astana.json.
Атрибуция: © OpenStreetMap contributors,
ODbL 1.0.
Во время работы интерфейса картографические API не вызываются.
На карте шесть контуров, но в расчёте остаются пять районов организаторов:
для Сарайшыка нет выдуманных показателей и выбора мер. Байконыр на карте
соответствует Байконуру (baikonur) в датасете.
AI: единственная внешняя интеграция анализа — OpenAI, используемый только
сервером в режиме agent. В режиме local приложение использует собственный
генератор объяснений без модели. Сценарии сохраняются в браузере, не в базе данных.
Ограничения текущей версии
- Реальный OpenAI ещё не проверен; качество поиска и расходы живой модели не подтверждены. Агент не гарантирует улучшение или глобально оптимальный набор.
- Локальное объяснение не является AI-агентом и не выполняет поиск альтернатив.
- Альтернатива передаётся текстом; структурированного применения одной кнопкой нет.
- Нет пользовательского сравнения двух сохранённых сценариев, PDF-экспорта, рейтинга команд и графиков Recharts. Сохранение ограничено одним планом в браузере.
- 3D-дома, робот и демонстрационные действия условные. Геометрия OSM не является подтверждённым официальным кадастровым слоем, а анимация — планом строительства.
- Приложение — хакатон-прототип: в текущем API нет аутентификации и ограничения частоты запросов между пользователями. Перед публичным доступом к платному AI нужны дополнительные меры защиты и контроля расходов.
Публичная демоверсия
Подтверждённая ссылка на deployed-версию в репозитории не указана. Воспроизводимый способ проверки сейчас — локальный запуск по инструкции выше.
Документация проекта
- Кейс и критерии оценки.
- Датасет, правила, формула и контрольный пример.
- Актуальная интеграция UI, движка и AI; HTTP и проверки.
- Происхождение геоданных и устройство 3D-демонстрации.
- Архитектурные границы, план команды, правила разработки.
В ранних документах сохранились исторические отметки «каркас», HTTP 501 и
«API ещё не подключён». Для текущего состояния интеграции ориентируйтесь на
этот README, docs/AI_INTEGRATION.md и код; требования организаторов и
исходный датасет остаются обязательными.
Авторы коммитов
История коммитов
- 2026-09-23 17:53docs: document complete simulator for hackathon juryaswqwsa
- 2026-09-23 17:38feat: integrate simulator UI with engine and AI explanationsaswqwsa
- 2026-09-23 17:07feat: integrate simulation engine and guard live agent runsaswqwsa
- 2026-09-23 17:48Merge verified simulator integration into mainAlmas
- 2026-09-23 17:14feat: refine city model with district houses and plan activitiesAlmas
- 2026-09-23 16:05feat: implement tool-driven city scenario agentaswqwsa
- 2026-09-23 16:31feat: add interactive 3D city and robot guideAlmas
- 2026-09-23 15:50feat: implement deterministic city simulation enginedydosdxd
Все коммиты (15)
- 2026-09-23 14:41chore: initialize hackathon project architectureaswqwsa
- 2026-09-23 17:35Update package.jsondydosdxd
- 2026-09-23 15:21feat: add city overview and decision selection UIAlmas
- 2026-09-23 14:15Add hackathon task and datasetaswqwsa
- 2026-09-23 16:58Update package.jsondydosdxd
- 2026-09-23 16:06Update tsconfig.jsondydosdxd
- 2026-09-23 15:21Fix formatting issues in tsconfig.jsondydosdxd
Структура репозитория (86 файлов)
.env.example .gitignore AGENTS.md README.md docs/AI_INTEGRATION.md docs/ARCHITECTURE.md docs/CASE.md docs/DATASET.md docs/GEODATA.md docs/PLAN.md e2e/smoke.spec.ts eslint.config.mjs next.config.ts package-lock.json package.json playwright.config.ts postcss.config.mjs scripts/build_astana.py scripts/fetch-astana.py src/app/api/analyze/route.test.ts src/app/api/analyze/route.ts src/app/globals.css src/app/layout.tsx src/app/page.tsx src/components/README.md src/components/city/city-layout.ts src/components/city/city-map.tsx src/components/city/city-robot.ts src/components/city/city-scene.ts src/components/city/city-studio.tsx src/components/city/construction.tsx src/components/city/district-panel.tsx src/components/city/geo-terrain.ts src/components/city/geodata/astana.json src/components/city/geography.test.ts src/components/city/geography.ts src/components/city/plan-activities.ts src/components/city/robot-ik.test.ts src/components/city/robot-ik.ts src/components/project-shell.test.tsx src/components/project-shell.tsx src/components/simulator/baseline.ts src/components/simulator/presentation.ts src/components/simulator/scenario-analysis.test.tsx src/components/simulator/scenario-analysis.tsx src/components/simulator/selection-adapter.test.ts src/components/simulator/selection-adapter.ts src/components/simulator/simulation-results.tsx src/data/dataset.test.ts src/data/dataset.ts src/domain/README.md src/domain/index.ts src/domain/score.ts src/domain/simulation-engine.ts src/domain/types.ts src/domain/validation.ts src/server/README.md src/server/__tests__/fixtures.ts src/server/agent-budget.test.ts src/server/agent-budget.ts src/server/agent-report.ts src/server/agent-sdk.test.ts src/server/agent-tools.test.ts src/server/agent-tools.ts src/server/agent.test.ts src/server/agent.ts src/server/analysis-error.ts src/server/analysis-prompt.ts src/server/analysis-schema.ts src/server/analyze-handler.test.ts src/server/analyze-handler.ts src/server/analyze.test.ts src/server/analyze.ts src/server/fallback.test.ts src/server/fallback.ts src/server/live-agent-check.test.ts src/server/live-agent-check.ts src/server/openai.test.ts src/server/openai.ts src/styles/city-studio.css src/test/setup.ts tests/domain/simulation-engine.test.ts tsconfig.json vitest.config.ts Датасет районов.txt Описание кейса.txt
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.