AAYMA
RU
Войти

Astana City Decision Lab

Городской симулятор «Аким на 5 часов» с 3D-картой Астаны.

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

О проекте

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

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

Суть

Городской симулятор «Аким на 5 часов» с 3D-картой Астаны. Пользователь выбирает 5 мер из 14 в пределах бюджета 100 и видит, как меняются Score и показатели районов. ИИ-советник объясняет результат.

Как устроено

Клиент (React и MapLibre 3D) отправляет выбранные решения в FastAPI. Ядро city_core на Python Decimal проверяет повторы, бюджет, районы, несовместимости и лимит в две меры на направление. Затем применяет эффекты с лагами на горизонте 8 кварталов, добавляет синергии и ограничивает показатели диапазоном 0–100. Score = 0.7 × средневзвешенный балл районов + 0.3 × балл слабейшего района − число показателей ниже 40. По кнопке каталог и готовый расчёт уходят в OpenAI gpt-6-sol (Flex, structured outputs) за объяснением. Сценарии сохраняются в localStorage.

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

  • Decimal arithmetic simulation
  • lagged effects
  • synergies
  • constraint validation
  • structured outputs
  • 3D map rendering

Метрики

68 тестов ядра и 22 теста API; контрольный пример: Score 52,56 → 56,54 (+3,99), критических значений стало 0 вместо 2

Особенности

Числа считаются точно на Decimal, в JSON передаются строками, а ИИ только объясняет готовый результат. Интерактивная 3D-карта Астаны на MapLibre. Работа разделена по веткам (клиент, API, ядро) и затем объединена через Docker Compose.

Стек

TypeScript · React · Vite · MapLibre GL JS · OpenFreeMap · Python · FastAPI · Pydantic · Docker Compose · Nginx · pytest · Ruff · mypy · ESLint

Модели

gpt-6-sol


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

README

README.md

Аким на 5 часов — Astana City Decision Lab

Пять решений. Один бюджет. Будущее Астаны.

Учебный AI-симулятор помогает увидеть, как распределение ограниченного городского бюджета влияет на качество жизни районов. Пользователь выбирает инициативы, сравнивает результат с исходным состоянием и получает объяснение последствий. Проект предназначен для участников кейса и демонстрации жюри хакатона.

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

  • Интерактивная карта Астаны с объёмными зданиями, переключением 2D/3D, вращением, масштабом и переходами к четырём городским ориентирам.
  • Каталог 14 мер в пяти направлениях: транспорт, экология, социальная сфера, безопасность и городские сервисы.
  • Выбор ровно пяти мер с бюджетом 100 и назначением района для локальных мер.
  • Проверка повторов, бюджета, районов, несовместимости и лимита двух мер одного направления; невалидный набор не получает расчётный результат.
  • Точный расчёт Astana Quality of Life Score, изменений пяти районов, показателей, критических значений и синергий.
  • ИИ-советник: сильные стороны, риски, последствия и рекомендации.
  • Сохранение до 20 именованных сценариев в браузере, повторное открытие, удаление и сравнение баллов в списке.

Как работает решение

  1. Пользователь открывает карту и выбирает пять инициатив с районами.
  2. Клиент показывает расходы и отправляет решения в FastAPI.
  3. Ядро проверяет ограничения и применяет эффекты мер с учётом лагов на горизонте восьми кварталов, затем добавляет синергии и ограничивает значения показателей диапазоном 0–100.
  4. Интерфейс показывает исходное и итоговое состояние, Score и дельты.
  5. По отдельной кнопке сервер передаёт каталог и готовый расчёт в OpenAI. Модель объясняет результат; числовой расчёт выполняется только ядром.
  6. Пользователь сохраняет вариант в браузере и может сравнить его с другими.

Формула ядра: Score = 0.7 × средневзвешенный балл районов + 0.3 × балл слабейшего района − количество показателей ниже 40. Арифметика использует Decimal; JSON передаёт десятичные значения строками, интерфейс округляет их только для отображения.

Технологии

КомпонентТехнологии
КлиентTypeScript, React 19.3, Vite 8.3, CSS Modules
КартаMapLibre GL JS 6.11, OpenFreeMap, OpenStreetMap / OpenMapTiles
APIPython 3.12, FastAPI 0.141, Pydantic 2.13, Uvicorn, HTTPX
ЯдроPython: dataclasses, decimal, без runtime-зависимостей
ИИOpenAI Chat Completions, gpt-6-sol, service_tier=flex, structured outputs
ХранениеVersioned localStorage, без серверной БД
Запуск и проверкиDocker Compose, Nginx, pytest, Ruff, mypy, ESLint, TypeScript

Полные версии зафиксированы в lock-файлах и requirements*.txt. ИИ настроен на Flex без автоматического перехода на Standard.

Архитектура

flowchart LR
  User[Пользователь] --> Client[React + MapLibre]
  Client --> Tiles[OpenFreeMap]
  Client <--> Storage[localStorage]
  Client --> Nginx[Nginx /api]
  Nginx --> API[FastAPI]
  API --> Core[city_core: валидация и Decimal]
  API --> AI[OpenAI: объяснение результата]

client/ отвечает за интерфейс. server/app/api/ — HTTP-контракт, server/app/agent/ — запрос к модели и проверку ответа. core/city_core/ содержит единственный каталог и формулы. API импортирует ядро как библиотеку; контейнер core дополнительно предоставляет CLI и после расчёта завершается. Клиент обращается к API через Nginx в одной origin. Ключ OpenAI передаётся только серверному контейнеру, не включается в клиентскую сборку.

МетодПутьНазначение
GET/api/healthСостояние API
GET/api/catalogКаталог и исходный результат
POST/api/scenarios/evaluateПроверка и расчёт набора решений
POST/api/scenarios/analyzeРасчёт и ИИ-объяснение

Установка и запуск

Нужны Git, Docker с Compose 2.20+ (используется include), Make и интернет для загрузки зависимостей, карты и OpenAI. Для просмотра 3D нужен браузер с WebGL. Node.js и Python на хосте для основного запуска не требуются.

git clone [email protected]:BAITC-Hacks/hack-22fca084-back-to-future.git
cd hack-22fca084-back-to-future
cp .env.example .env

Если репозиторий приватный, нужен доступ к нему. При повторном запуске сохраните существующий .env. Настройки:

ПеременнаяЗначение примераНазначение
CLIENT_PORT8040Локальный порт интерфейса
API_PORT8050Локальный порт API и Swagger
OPENAI_API_KEYпустоНеобязательный ключ для ИИ-анализа
OPENAI_MODELgpt-6-solМодель с доступом у вашего API-проекта

Добавьте ключ в .env, если нужен ИИ-анализ, и запустите:

make up

Откройте приложение и документацию API. При занятых портах измените .env. Сервисы публикуются на 127.0.0.1. Без ключа работают карта, каталог, расчёт и сохранения; анализ возвращает явный статус unavailable. При ошибке провайдера расчёт сохраняется.

make ps
make logs
make down

make down останавливает контейнеры. Сохранённые сценарии остаются в браузере. Для запуска итоговой ветки соседние клоны участников не нужны.

Как проверить решение

Сценарий для жюри

  1. Откройте приложение и нажмите «Пример из кейса».
  2. Убедитесь, что выбраны школа с детсадом, поликлиника и Safe City для Нуры, платформа обращений для города и чистое топливо для Сарыарки.
  3. Нажмите «Рассчитать будущее города».
  4. Ожидаемый результат: расходы 95, остаток 5, исходный Score 52.55768, итоговый 56.54307, прирост 3.98539. На экране это 52,56 → 56,54, прирост +3,99. Количество критических значений уменьшается с 2 до 0.
  5. Откройте показатели и синергии; при настроенном ключе нажмите «Проанализировать с ИИ» и дождитесь ответа советника.
  6. Введите название, сохраните сценарий и откройте вкладку «Сценарии».
  7. Для негативной проверки сбросьте решения и запустите расчёт: появится ошибка о необходимости выбрать ровно пять мероприятий.

Проверка HTTP без браузера:

curl -fsS http://localhost:8040/api/health
curl -fsS http://localhost:8040/api/scenarios/evaluate \
  -H 'Content-Type: application/json' \
  --data-binary @core/tests/fixtures/example_95.json

Проверки Python в контейнерах:

make core-check
make api-check

Клиентские проверки (Node.js 22.12+ на хосте):

npm --prefix client ci
npm --prefix client run typecheck
npm --prefix client run lint
npm --prefix client run test

После объединения прошли 68 тестов ядра и 22 теста API с Ruff/mypy; общий Compose собрался и запустился. До объединения прошли клиентские типы, линтер и production-сборка. В браузере проверены пример, невалидный набор, сохранение и живой ответ ИИ. Полный многократный прогон золотого набора ИИ не проводился; кейсы находятся в server/evals/cases.json.

Данные и интеграции

  • География: OpenStreetMap через тайлы OpenFreeMap/OpenMapTiles. Атрибуция сохранена на карте. Ключ картографического сервиса не требуется.
  • Расчётные данные: синтетический набор задания — пять условных районов, десять показателей, четырнадцать мер, веса, лаги и ограничения в core/city_core/catalog.py. Это не актуальная статистика Астаны.
  • OpenAI: сервер отправляет каталог и результат симуляции в https://api.openai.com/v1/chat/completions. Ключ берётся из окружения. Генерация не вызывается для невалидного сценария.

Ограничения текущей версии

  • Демонстрационная модель, не прогноз развития реального города.
  • 3D-здания — объёмные контуры с доступными или приближёнными высотами, без фотореалистичных фасадов и точных моделей всех достопримечательностей.
  • Границы расчётных районов не нанесены на карту; показатели показаны карточками.
  • Нет регистрации, общей БД, синхронизации сценариев между устройствами и серверной истории. Очистка данных браузера удаляет сохранения.
  • Сравнение сохранений доступно по Score и приросту в списке, без отдельного подробного сравнительного отчёта.
  • Карта и ИИ зависят от внешних сервисов. Flex может отвечать дольше или быть временно недоступен; таймаут запроса к модели — 180 секунд.
  • Структура ответа ИИ проверяется, но это не гарантия фактической точности каждой рекомендации. Полный золотой прогон и нагрузочные тесты не выполнены.
  • Публичный деплой, HTTPS и промышленная эксплуатация не настроены.

Демо и команда

Публичной deployed-версии сейчас нет. Локальное демо после make up: http://localhost:8040.

УчастникЧасть решенияВетка
Ульданов МансурКлиент и 3D-картаmansur
Уралбаев АлишерAPI и ИИ-советникalisher
Далиев ДосжанРасчётное ядроdoszhan

Общая сборка — main. Подробности расчётного контракта: core-contract, карта файлов: CODEMAP.

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

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

Doszhan 5Ульданов Мансур 3Уралбаев Алишер 2Далиев Досжан 1m.uldanov 1

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

  • 2026-09-23 17:59Объединить клиент API и ядро и описать запуск для жюриУльданов Мансур
  • 2026-09-23 17:52Добавить панель городских решений и сквозное демоУльданов Мансур
  • 2026-09-23 17:40Настроить gpt-6-sol в режиме FlexУралбаев Алишер
  • 2026-09-23 17:34Добавить API сценариев и анализ результатов через OpenAIУралбаев Алишер
  • 2026-09-23 17:18Добавить точное расчётное ядро городского симулятораДалиев Досжан
  • 2026-09-23 16:59Добавить трёхмерную карту Астаны с управлением камеройУльданов Мансур
  • 2026-09-23 16:02aDoszhan
  • 2026-09-23 16:01rm: textDoszhan
Все коммиты (12)
  • 2026-09-23 16:01textDoszhan
  • 2026-09-23 10:17rm text.txtDoszhan
  • 2026-09-23 10:14testDoszhan
  • 2026-09-23 09:45exmaplem.uldanov
Структура репозитория (91 файлов)
.dockerignore
.env.example
.githooks/commit-msg
.githooks/pre-commit
.gitignore
CODEMAP.md
Makefile
README.md
STACK.md
client/Dockerfile
client/eslint.config.js
client/index.html
client/package-lock.json
client/package.json
client/src/features/map/mapConfig.ts
client/src/features/map/mapStyle.ts
client/src/features/map/useCityMap.ts
client/src/features/simulator/ResultsPanel.tsx
client/src/features/simulator/ScenarioPanel.tsx
client/src/features/simulator/Simulator.module.css
client/src/features/simulator/storage.ts
client/src/features/simulator/useSimulator.ts
client/src/main.tsx
client/src/pages/MapPage.module.css
client/src/pages/MapPage.tsx
client/src/shared/api/client.ts
client/src/shared/api/types.ts
client/src/shared/ui/ErrorBoundary.tsx
client/src/shared/ui/Icon.tsx
client/src/styles/global.css
client/tests/production.test.mjs
client/tsconfig.json
client/vite.config.ts
core/.dockerignore
core/Dockerfile
core/city_core/__init__.py
core/city_core/__main__.py
core/city_core/calculator.py
core/city_core/catalog.py
core/city_core/cli.py
core/city_core/models.py
core/city_core/serialization.py
core/city_core/validation.py
core/compose.yml
core/pyproject.toml
core/requirements-dev.in
core/requirements-dev.txt
core/tests/conftest.py
core/tests/fixtures/cheapest_61.json
core/tests/fixtures/example_95.json
core/tests/fixtures/over_budget.json
core/tests/test_calculator.py
core/tests/test_catalog.py
core/tests/test_cli.py
core/tests/test_validation.py
deploy/nginx/nginx.conf
docker-compose.preview.yml
docker-compose.yml
docs/api-plan.md
docs/core-contract.md
docs/core-plan.md
docs/core-usage.md
docs/map-prototype-plan.md
docs/merge-plan.md
docs/simulator-plan.md
make/compose.mk
server/Dockerfile
server/app/__init__.py
server/app/agent/__init__.py
server/app/agent/prompt.md
server/app/agent/provider.py
server/app/api/__init__.py
server/app/api/analysis.py
server/app/api/catalog.py
server/app/api/health.py
server/app/api/scenarios.py
server/app/config.py
server/app/core_adapter.py
server/app/errors.py
server/app/logging.py
server/app/main.py
server/app/schemas.py
server/compose.yml
server/evals/cases.json
server/pyproject.toml
server/requirements-dev.in
server/requirements-dev.txt
server/requirements.in
server/requirements.txt
server/tests/conftest.py
server/tests/test_api.py
Ветки (4)

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

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

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