AAYMA
RU
Войти

Аким на 5 часов

Веб-симулятор «Аким на 5 часов» на Next.js.

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

О проекте

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

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

Суть

Веб-симулятор «Аким на 5 часов» на Next.js. Детерминированный движок Score, проигрывание 8 кварталов, жадный «Аким-автомат» для сравнения, совет из 4 LLM-агентов с секретарём и чат «Спросить город» на трёх языках.

Как устроено

Функции lib/engine validate(), simulate(), yearFrames(), recommend(), coach() и rivalPlan() считают Score по data/city.json (лаг (8−L)/8, синергии, клиппинг, штраф за значения ниже 40). Этот журнал — единственный источник чисел. Совет из четырёх агентов и секретаря (xAI grok-4.7 через пакет openai, ответы проверяются Zod) объясняет журнал, при недоступности модели доклад собирается по шаблону. Есть жадный рекомендатель следующего хода, «Тень другого решения» с пересчитанной дельтой, полка прогонов в data/runs.json и сравнение наборов. Карта на Leaflet/OSM.

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

  • детерминированный simulate()
  • жадный rival-план («Аким-автомат»)
  • coach/рекомендация следующего хода
  • мультиагентный совет + секретарь
  • Zod-валидация структурированных ответов
  • поквартальное проигрывание эффекта
  • интерфейс RU/KK/EN

Особенности

Используется xAI Grok вместо OpenAI. Совет агентов может открыть карточку района, но числа берёт только из журнала. Интерфейс трилингвальный (рус/каз/англ), язык и тема переключаются фразами в чате. Есть портативный запуск через Akim.exe. В корне лежат посторонние файлы jev/laya_routing.py.

Стек

TypeScript · Next.js 15 · React 19 · Tailwind CSS 4 · Zod · Leaflet · OpenStreetMap · Vitest · C# (launcher Akim.exe)

Модели

grok-4.7 (xAI)


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

README

README.md

Аким на 5 часов

1. Название проекта

Аким на 5 часов

2. Краткое описание

Городскому управленцу, аналитику или команде на хакатоне нужно распределить один и тот же ограниченный бюджет между транспортом, экологией, соцсферой, безопасностью и городскими сервисами и понять, как это меняет качество среды.

Проект — веб-симулятор. Все начинают с бюджета 100 и одного синтетического набора: пять районов и десять показателей. Команда выбирает ровно пять мероприятий. Город отвечает баллом Score: 70% — средний уровень, 30% — самый слабый район, минус один балл за каждый показатель ниже 40. Рядом с числом есть объяснение компромиссов.

Районы и показатели условные. Это не официальная статистика, персональных данных в проекте нет.

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

  • Каталог из 14 мер и бюджет 100. Ровно пять мер, без повторов. Для районной меры обязателен район, для городской район не указывается.
  • Проверка набора: превышение бюджета, больше двух мер одного направления, запрещённые пары (полосы и ЛРТ; парк и школа в одном районе; чистое топливо и модернизация сетей в одном районе). Недопустимый набор балл не получает, причина показывается в интерфейсе и возвращается сервером.
  • Расчёт Score, среднего уровня, самого слабого района и числа показателей строго ниже 40. Остаток бюджета балл не повышает.
  • Лаг на горизонте 8 кварталов: доля эффекта (8 − L) / 8. Три синергии прибавляются целиком и лагом не режутся.
  • Живой экран набора: пять слотов, полоска бюджета, поиск по каталогу, фильтр мер для самого слабого района, список правил, показатели ниже 40 и статус синергий.
  • Совет следующего хода: движок достраивает пятёрку и показывает три сильных первых шага. На карточке указан Score, если дальше тоже брать сильные ходы.
  • Доклад: сильные стороны, риски, последствия на 8 кварталов, реплики вымышленных жителей, таблица районов и «Тень другого решения» с пересчитанной дельтой.
  • Проигрывание восьми кварталов. Мера молчит свой лаг, затем каждый квартал добавляет одну восьмую эффекта. На 8-м квартале Score совпадает с итогом.
  • Аким-автомат: жадный набор на том же каталоге. Его балл сравнивается с набором команды, набор можно открыть на экране решений.
  • Карта OpenStreetMap с примерными точками пяти районов и локальными изображениями-образами районов.
  • Полка прогонов на этой машине и сравнение двух последних наборов.
  • Совет из четырёх агентов и секретаря, если задан ключ. Секретарь может открыть карточку района. Числа берутся из журнала. Если ключа нет, ответ не сошёлся или совет не успел, остаётся доклад по журналу.
  • Кнопка «Спросить город»: диалог о текущем наборе. Фразы вроде «қазақша», «english» и «ночная тема» переключают язык и оформление. Языки интерфейса: русский, қазақша, English. Оформление: бумага, ночь, степь.
  • Печать доклада из браузера и проверка GET /api/health.

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

  1. На старте команда видит бюджет 100, базовый Score 52,56 и карту пяти районов. Два показателя ниже 40 — школы и поликлиники Нуры.
  2. Команда набирает пять мер. Районная мера требует район, городская действует на всех. Интерфейс показывает остаток бюджета, правила и проекцию районов.
  3. «Открыть доклад» запускает расчёт. Движок применяет лаг и синергии, обрезает показатели в диапазон 0…100 и считает Score.
  4. На докладе видны сильные стороны, риски, последствия, карта и таблица «было / стало». Ползунок кварталов показывает, когда меры начинают работать.
  5. Если задан ключ, совет объясняет уже посчитанный журнал. Иначе текст собирается из этого журнала.
  6. Прогон можно положить на полку и сравнить с другим. Соседний набор из «Тени другого решения» можно подставить и пересчитать.

Контрольный пример методики: школа и поликлиника в Нуре, камеры в Нуре, городская платформа обращений, чистое топливо в Сарыарке. Стоимость 95, Score 56,54, провалов 0, синергия M10+M12.

5. Технологии

  • TypeScript, React 19, Next.js 15 (App Router), Tailwind CSS 4
  • Шрифты Fraunces и Source Sans 3 из пакетов @fontsource
  • Vitest и tsx
  • Zod для проверки структурированных ответов совета
  • Leaflet и тайлы OpenStreetMap
  • Пакет openai как клиент к OpenAI-совместимому API
  • Модель по умолчанию grok-4.7, адрес https://api.x.ai/v1, ключ XAI_API_KEY, имя модели можно задать переменной XAI_MODEL

В репозитории нет вызовов api.openai.com и NVIDIA API.

6. Архитектура проекта

браузер
  старт, набор, доклад, формула, полка, чат
        │
        ▼
lib/engine
  validate()  simulate()  yearFrames()
  recommend() coach()     rivalPlan()
        │
        ▼
журнал: Score, средний, пол, провалы, синергии, вклады мер
        │
        ├─ доклад по журналу, если модели нет
        ├─ POST /api/analyze   совет и секретарь
        ├─ POST /api/chat      ответ на вопрос по снимку набора
        ├─ POST /api/compare   сравнение двух наборов
        ├─ GET, POST /api/runs полка в data/runs.json
        └─ GET /api/health     версия данных и базовый Score

Балл считает только simulate() в lib/engine. Клиент и сервер вызывают одну функцию. Модель объясняет готовый журнал и не является источником числа. Данные лежат в data/city.json, версия astana-rules-v2.

Экраны: /, /decide, /report, /method, /compare.

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

Нужен Node.js LTS. Команды из папки проекта в PowerShell:

npm install
copy .env.example .env
npm test
npm run demo
npm run dev

Открыть http://localhost:3000

Файл .env в git не попадает. Ключ можно оставить пустым. Для живого совета его записывают только локально и не публикуют в GitHub:

XAI_API_KEY=
XAI_MODEL=grok-4.7

На Windows файл start-local.cmd проверяет Node.js, при первом запуске выполняет npm install, создаёт .env из примера и открывает http://localhost:3000

Akim.exe в папке проекта — окно запуска. Рядом должны быть package.json, установленные node_modules и Node.js в PATH. Окно поднимает сервер на http://localhost:4173 и открывает браузер. Закрытие окна останавливает сервер.

После npm run build сервер запускается командой npm start.

Полная проверка типов, тестов и контрольных чисел:

npm run check

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

Без браузера:

npm test
npm run demo

npm run demo печатает три строки. На текущих данных это:

  • база: Score 52.56, средний 56.86, пол 49.18, район nura, критических провалов 2, резерв 100;
  • пример методики: Score 56.54, средний 58.08, пол 52.96, провалов 0, резерв 5, синергия M10+M12;
  • дешёвый набор: Score 53.80, средний 58.10, пол 50.43, провалов 2, резерв 39, синергия M10+M12.

Тесты дополнительно проверяют бюджет, число мер, повторы, лимит направления, конфликты, лаг, восьмой квартал и акима-автомата.

После запуска сервера:

curl http://localhost:3000/api/health

В ответе есть ok, версия данных и базовый Score.

В браузере:

  1. Открыть старт, ввести имя команды и нажать «Собрать набор».
  2. На экране набора нажать «Пример». Score около 56,54, остаток 5, провалов 0.
  3. Открыть доклад. Есть сильные стороны, риски, карта и таблица районов.
  4. Нажать «Смотреть два года» или сдвинуть ползунок кварталов. На 8-м квартале балл совпадает с итогом.
  5. Открыть «Тень другого решения» или «Открыть его набор» у акима-автомата. Набор и балл меняются.
  6. Положить прогон на полку, повторить с другим набором и нажать «Сравнить две последние».
  7. Нажать «Спросить город» и задать вопрос про текущий балл. В ответе не должно быть кода.

Набор дороже 100 через POST /api/analyze возвращает статус 400, модель при этом не вызывается.

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

  • data/city.json: пять районов (Есиль, Алматы, Сарыарка, Байконур, Нура), доли населения, десять показателей от 0 до 100, 14 мер с ценой, лагом и эффектами, три синергии, три несовместимости, пять вымышленных жителей. Шкала направлена одинаково: 100 — лучше. Пробки и смог уже перевёрнуты.
  • Изображения районов лежат в public/districts. Это образы для симулятора, не официальная фотофиксация.
  • Карта запрашивает тайлы https://{s}.tile.openstreetmap.org. Точки районов примерные, это не официальные границы. Без интернета снимки остаются, подложка карты не загружается.
  • Живые ответы модели идут только с сервера на https://api.x.ai/v1 после расчёта или по снимку набора: POST /api/analyze, POST /api/chat, POST /api/compare.
  • Прогоны команд пишутся в data/runs.json на машине, где запущен сервер. Файл указан в .gitignore.
  • Вызовов API OpenAI и NVIDIA в коде нет.

10. Ограничения

  • Данные синтетические и не заменяют официальную статистику города.
  • Нет учётных записей и нет общей полки между разными компьютерами.
  • Без XAI_API_KEY и сети живой совет, сравнение моделью и свободный ответ в чате недоступны. Score, журнал, кварталы, аким-автомат, тень решения, полка и доклад по журналу продолжают работать.
  • Названия мер в каталоге остаются на русском. Переводятся шапка, старт и подписи набора.
  • Печать — страница браузера. Отдельный файл презентации проект не собирает.
  • Akim.exe не заменяет установку Node.js: это окно запуска для уже собранной папки проекта.
  • Публичной deployed-версии в репозитории нет.

11. Ссылка на deployed-версию

Развёрнутой публичной версии нет.

Локальные адреса после запуска:

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

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

Никита 10Kukumbus 2nurba112 1

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

  • 2026-09-23 17:37Merge remote-tracking branch 'origin/main'Никита
  • 2026-09-23 17:37Sync current project READMEНикита
  • 2026-09-23 17:32Update README.mdKukumbus
  • 2026-09-23 17:15Point README to cleaned portable packageНикита
  • 2026-09-23 17:10Clarify local runtime and portable releaseНикита
  • 2026-09-23 16:43Prepare HackAlem release with Akim.exe and READMEНикита
  • 2026-09-23 16:21Add scenario comparison and district insightsНикита
  • 2026-09-23 15:56Merge remote-tracking branch 'origin/main'Никита
Все коммиты (13)
  • 2026-09-23 15:56Harden local app checks and runtime handlingНикита
  • 2026-09-23 15:47Add files via uploadKukumbus
  • 2026-09-23 15:18Add files via uploadnurba112
  • 2026-09-23 14:49Add one-click local launcherНикита
  • 2026-09-23 14:36Add Akim na 5 chasov applicationНикита
Структура репозитория (74 файлов)
.env.example
.gitignore
AGENTS.md
Akim.exe
CHANGELOG.md
README.md
app/api/analyze/route.ts
app/api/chat/route.ts
app/api/compare/route.ts
app/api/health/route.ts
app/api/runs/route.ts
app/compare/page.tsx
app/decide/page.tsx
app/globals.css
app/icon.svg
app/layout.tsx
app/method/page.tsx
app/page.tsx
app/report/page.tsx
components/Assistant.tsx
components/CityMap.tsx
components/Frame.tsx
components/RealMap.tsx
components/ScorePlate.tsx
components/score-color.ts
data/city.json
docs/PLAN.md
docs/PROMPTS.md
jev_adapter.py
jev_routing.py
launcher/Program.cs
laya_adapter.py
laya_routing.py
lib/ai/briefing.ts
lib/ai/compare.ts
lib/ai/council.ts
lib/ai/evidence.ts
lib/ai/fallback.test.ts
lib/ai/fallback.ts
lib/ai/prompts.ts
lib/ai/schemas.ts
lib/assistant-commands.test.ts
lib/assistant-commands.ts
lib/draft.ts
lib/engine/canon.ts
lib/engine/city.ts
lib/engine/coach.ts
lib/engine/demo.ts
lib/engine/format.ts
lib/engine/insights.ts
lib/engine/places.ts
lib/engine/present.ts
lib/engine/recommend.ts
lib/engine/simulate.test.ts
lib/engine/simulate.ts
lib/engine/types.ts
lib/plain-speech.test.ts
lib/plain-speech.ts
lib/prefs.tsx
lib/store/runs.ts
maker_backends.py
next-env.d.ts
next.config.ts
package-lock.json
package.json
postcss.config.mjs
public/districts/almaty.jpg
public/districts/baikonur.jpg
public/districts/esil.jpg
public/districts/nura.jpg
public/districts/saryarka.jpg
start-local.cmd
tsconfig.json
vitest.config.ts

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

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

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