AAYMA
RU
Войти

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

Веб-симулятор, где игрок выбирает 5 городских мер в пределах бюджета 100 единиц и получает оценку по направлениям и районам.

Прототип
Команда «NT» 2💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: NT
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Прототип

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

Суть

Веб-симулятор, где игрок выбирает 5 городских мер в пределах бюджета 100 единиц и получает оценку по направлениям и районам. Затем моделируется событие (например, отмена стройки школы), игрок выбирает замену и сравнивает результаты.

Как устроено

Детерминированный движок проверяет план (5 уникальных мер, не больше 2 на направление, район для районных мер) и считает эффекты, лаги и синергии на горизонте 8 кварталов по каталогу organizer-v1. Отдельные эндпоинты делают предпросмотр и подтверждение замены после события с ранжированием вариантов. /api/explain объясняет проверенные факты симуляции на RU, KK и EN через OpenAI или по шаблону. UI на Next.js пока работает на mock-сценариях demo-v1 и к новому API не подключён.

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

  • deterministic scoring engine
  • constraint validation
  • event cancellation & ranked replacement
  • synergies/lags
  • template + LLM explanation

Особенности

Работа разделена на три параллельные части (UI, движок, API/AI) по общему контракту shared-contract-v1, промпты для AI-кодинга лежат в prompts/. Есть golden-фикстуры с эталонным Score 56.54307. README прямо предупреждает, что UI не подключён к настоящему движку и работает только на подготовленных сценариях.

Стек

TypeScript · Next.js · React · Vitest · Playwright · Node.js

Модели

OpenAI (OPENAI_MODEL)


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

README

README.md

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

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

Сценарий: пять решений → результат → событие → замена → сравнение.

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

Текущее состояние

Общая версия main объединяет интерфейс Semba, движок Nikita и API/AI Bakytzhan. Интерфейс включает обновлённый дизайн: белую основу, зелёные основные действия, синие информационные акценты и жёлтые уведомления.

Интерфейс пока работает на подготовленных mock-сценариях demo-v1. Новый расчётный API organizer-v1 также включён в main. Подключение интерфейса к нему, выбор районов и языка ещё не завершены. Переключение одного env-флага не выполняет эту интеграцию. Публичный сайт и доступ браузера к платному AI пока не настроены. Одного AI_ENABLED=true для такого доступа недостаточно.

Для показа жюри используйте описанный ниже браузерный сценарий. API-ключ, база данных и Docker для него не нужны.

Запуск для жюри

1. Что установить

  • Node.js 24.x с npm.
  • Git.
  • Современный браузер.
  • Доступ к приватному репозиторию команды.

Интернет понадобится для скачивания проекта и установки зависимостей. Заранее подготовленное локальное mock-демо не обращается к AI-провайдеру.

2. Скачать проект

Откройте терминал и выполните:

git clone --branch main https://github.com/BAITC-Hacks/hack-14dc5002-nt.git
cd hack-14dc5002-nt
npm ci

Ветка main содержит общую проверенную версию команды. Если GitHub сообщает Repository not found, проверьте доступ вашего аккаунта к приватному репозиторию.

Если проект уже скачан, сохраните свои незакоммиченные изменения, затем обновите чистую рабочую копию:

git switch main
git pull --ff-only origin main
npm ci

3. Создать настройки

В корне проекта, рядом с package.json, создайте файл .env.local:

NEXT_PUBLIC_USE_MOCK_API=true
AI_ENABLED=false

Если файл уже существует, измените только эти значения и сохраните остальные настройки. На Windows убедитесь, что имя файла не стало .env.local.txt.

Для этого показа OPENAI_API_KEY и OPENAI_MODEL не нужны. Файл .env.local исключён из Git; передавать секреты жюри не требуется.

4. Собрать и запустить

Если сервер проекта уже работает в другом терминале, сначала остановите его сочетанием Ctrl+C.

npm run build
npm run start -- --hostname 127.0.0.1 --port 3000

Откройте http://127.0.0.1:3000.

Оставьте терминал открытым до конца демонстрации. Для остановки приложения нажмите Ctrl+C.

На странице должны быть видны:

  • заголовок «Как изменится город от ваших решений?»;
  • пометки «Демо-сценарии» и «Модель demo-v1»;
  • бюджет 100 условных единиц;
  • кнопки «Загрузить демо-план» и «Рассчитать результат».

Альтернатива: запуск для разработки

Вместо production-сборки и start можно выполнить:

npm run dev -- --hostname 127.0.0.1 --port 3000

Адрес остаётся тем же. В этом режиме изменения кода автоматически появляются в браузере. Не запускайте оба режима одновременно на одном порту.

NEXT_PUBLIC_USE_MOCK_API встраивается в браузерный код при сборке. После изменения значения перезапустите dev-сервер либо заново выполните npm run build и перезапустите production-сервер. Настройки самого терминала могут перекрывать значения из .env.local.

Что показать жюри

Для чистого начала удобно открыть приложение в приватном окне: обычный браузер может восстановить ранее сохранённый базовый план.

  1. Нажмите «Загрузить демо-план». Будут выбраны пять мероприятий: выделенные автобусные полосы, строительство школы, озеленение общественных пространств, освещение безопасных маршрутов и городские услуги онлайн.
  2. Нажмите «Рассчитать результат». Покажите 5 / 5 выбранных мероприятий, расходы 90 / 100, результат 57, показатели направлений и районов.
  3. Перейдите к разделу «Что изменилось?». В карточке «Строительство школы отменено: участок недоступен» нажмите «Смоделировать событие».
  4. Покажите, что в промежуточном плане осталось 4 мероприятия, его результат не рассчитывается, а для замены доступно 40 единиц. Исходный снимок остаётся сохранённым.
  5. Выберите именно «Модульные учебные корпуса». Нажмите «Подтвердить выбранную замену». Не выбирайте автоматически первую рекомендацию: старый mock поддерживает не все варианты подтверждения.
  6. Покажите сравнение: исходный результат 57 при расходах 90, новый результат 56,6 при расходах 96, изменение −0,4. Симулятор показывает компромисс: замена не обязана улучшать общий балл.
  7. В блоке «Объяснение последствий», после подтверждения замены, нажмите «Получить объяснение». Появится текст с пометкой «Шаблонное объяснение».
  8. При необходимости перезагрузите страницу: исходный план восстановится, ветка события сбросится. Для повторного показа снова загрузите демо-план.
Этап demo-v1МероприятийРасходыОстаток / доступноScore
Исходный план5901057
После отмены школы46040Отсутствует
После замены на модульные корпуса596456,6

Краткий текст для защиты

«Мы показываем интерфейс на подготовленном демонстрационном сценарии. Пользователь распределяет ограниченный бюджет между пятью городскими мерами. После отмены одного решения исходный план сохраняется, а в отдельном сценарии можно выбрать замену и сравнить последствия. Новый расчётный движок готовится к подключению к этому интерфейсу. Данные учебные и синтетические».

Границы текущего показа

  • Числа в браузерном mock-режиме берутся из подготовленных fixtures.
  • Произвольные комбинации могут вернуть MOCK_SCENARIO_NOT_DEFINED.
  • Объяснение базового плана в старом mock не подготовлено. Показывайте объяснение после подтверждения замены школы.
  • Пометка template означает шаблон; этот показ не подтверждает вызов AI.
  • Сохранённый базовый план и ветка события разделены. Изменение выбора не переписывает исходный снимок до нового расчёта.
  • Подсказки несовместимости и зависимостей описывают правила. Жёлтое предупреждение появляется при нарушении в текущем выборе.

Что уже реализовано в интерфейсе

  • Каталог мероприятий с фильтрами по направлениям.
  • Стоимость, задержка эффекта, эффекты по районам и ограничения.
  • Выбор до пяти мероприятий и предварительный бюджет.
  • Крупный результат, показатели направлений и районные карточки.
  • Отдельный сценарий отмены, предварительные варианты и подтверждение замены.
  • Сравнение исходного и нового плана.
  • Состояния загрузки, ошибок и шаблонного объяснения.
  • Сохранение базового плана с версией модели в localStorage.
  • Адаптивная вёрстка и навигация по трём этапам работы.

Новый API: серверная часть в том же приложении

Новая серверная реализация включена в main. Она использует organizer-v1, а не модель браузерного демо выше:

Параметрdemo-v1 в текущем UIorganizer-v1 в новом API
РайоныУсловные D1–D3Есиль, Алматы, Сарыарка, Байконур, Нура
Каталог16 мер, включая меру события14 мер
Горизонт12 месяцев8 кварталов
Формат планаactionIdsselections: [{actionId, districtId?}]
Эталонный расход9095
Эталонный Score5756.54307
Языки объясненийПодготовленный русский mockru, kk, en

Числа этих моделей не взаимозаменяемы. Не переключайте текущий интерфейс на новый API только изменением флага.

Сервер organizer-v1 принимает пять уникальных мер в пределах 100 единиц, не более двух мер одного направления. Для районных мер требуется район; для городских район не передаётся. Сервер проверяет ограничения и рассчитывает эффекты, лаги и синергии. События отмены и обязательной меры — сценарии команды.

Отдельный запуск серверной версии

Этот раздел необязателен для браузерного показа жюри. Все серверные маршруты уже работают в запущенном выше приложении, даже при клиентском mock-флаге true. Для отдельной проверки API можно использовать другую папку:

git clone --branch main https://github.com/BAITC-Hacks/hack-14dc5002-nt.git hackalem-api
cd hackalem-api
npm ci

Создайте в этой папке .env.local:

NEXT_PUBLIC_USE_MOCK_API=false
AI_ENABLED=false
AI_LOCAL_DEMO=false

Запустите API на отдельном порту:

npm run dev:local -- --port 3001

Каталог будет доступен по http://127.0.0.1:3001/api/catalog. Главная страница этой серверной версии ещё не является новым подключённым UI.

Пример получения реального расчёта в PowerShell, во втором терминале:

$apiBase = 'http://127.0.0.1:3001'
$catalog = (Invoke-RestMethod -Uri ($apiBase + '/api/catalog')).data
$body = $catalog.demoPlan | ConvertTo-Json -Depth 20
$result = Invoke-RestMethod -Uri ($apiBase + '/api/simulate') -Method Post `
    -ContentType 'application/json; charset=utf-8' `
    -Body ([System.Text.Encoding]::UTF8.GetBytes($body))
$result.data | Select-Object valid, totalCost, remainingBudget, officialScore

Для эталонного плана organizer-v1 ожидаются valid=true, totalCost=95, remainingBudget=5, officialScore=56.54307.

МетодМаршрут нового APIНазначение
GET/api/catalogКаталог и сценарии команды
POST/api/simulateПроверка и расчёт плана
POST/api/events/previewПредварительные допустимые замены
POST/api/events/confirmПодтверждение одной замены
POST/api/explainОбъяснение результата на RU/KK/EN

Полный контракт, примеры событий и объяснений: инструкция интеграции.

Роль AI

Числа рассчитывает детерминированный движок, а не языковая модель. В новом API сначала создаются проверенные факты. При включённом AI модель выбирает факты и их порядок; текст и числовые значения формирует сервер.

При выключенном AI, отсутствии настроек, ошибке или таймауте возвращается source=template. Для показа жюри оставьте AI_ENABLED=false. Опциональное подключение AI описано в инструкции интеграции. Обычный production-браузер пока получает шаблон; публичный доступ к платным вызовам требует отдельной настройки и общего серверного лимита.

Ключи хранятся только на сервере. Не добавляйте их в Git или в переменные с префиксом NEXT_PUBLIC_.

Если приложение не запускается

СимптомРешение
node или npm не найденУстановите Node.js 24.x и заново откройте терминал
PowerShell блокирует npm.ps1Используйте npm.cmd ci, npm.cmd run build, npm.cmd run start -- --hostname 127.0.0.1 --port 3000
GitHub сообщает Repository not foundПроверьте адрес и доступ аккаунта к приватному репозиторию
EADDRINUSEОстановите предыдущий сервер или используйте npm run start -- --hostname 127.0.0.1 --port 3002 и откройте порт 3002
Could not find a production buildСначала выполните npm run build и дождитесь завершения
Сайт не открываетсяПроверьте, что сервер работает, терминал открыт и адрес содержит правильный порт
MOCK_SCENARIO_NOT_DEFINEDЗагрузите демо-план и повторите точную последовательность показа
Неверный каталог или UI_CONTRACT_OUTDATEDДля текущего UI нужен NEXT_PUBLIC_USE_MOCK_API=true; после изменения пересоберите приложение
После изменения env режим прежнийПроверьте переменные терминала, остановите сервер, пересоберите и запустите снова
Показывается предыдущий планОткройте приватное окно либо загрузите демо-план и пересчитайте
Объяснение помечено как шаблонЭто ожидаемый режим демонстрации без AI

Технологии и структура интерфейса

Next.js 15, React 19, TypeScript, серверные маршруты в одном приложении, Zod для проверки входных данных. Авторизация пользователей и база данных для локального MVP не требуются.

src/
  app/
    page.tsx              Страница приложения
    globals.css           Общие стили
    api/                  Серверные маршруты текущей ветки
  features/dashboard/
    SimulationDashboard.tsx   Интерфейс и состояние сценария
    stored-plan.ts            Чтение сохранённых ID и версии модели
  contracts/              Типы данных
  data/                   Каталог
  lib/client-api.ts       Адаптер текущего UI
  mocks/                  Подготовленные сценарии demo-v1
docs/                     Описание проекта и интеграции

localStorage сохраняет план и версию модели. Сохранённые числовые результаты не используются как доверенный источник: план проверяется повторно.

Проверки общей версии

После объединения интерфейса Semba c0bf5d6 и сервера Bakytzhan 710d106 выполнены следующие проверки. Последующие изменения касаются документации.

КомандаРезультат
npm run typecheckPASS
npm run lint0 ошибок, 4 предупреждения в старых заглушках движка
npm test132 Vitest + 77 тестов движка — PASS
node verification/check-fixtures.mjs581 проверка — PASS
npm run test:e2e10 проверок mock UI, Edge desktop/mobile — PASS
npm run test:api:e2e2 HTTP-сценария реального API — PASS
npm run buildPASS, mock UI, без ключа и платного AI

GitHub Actions отключён по решению команды; это результаты локальных проверок. Для браузерных тестов установите Chromium (npx playwright install chromium) или на Windows задайте $env:PLAYWRIGHT_CHANNEL='msedge' для установленного Edge. Полный отчёт и ограничения — docs/DEMO.md.

Команда и документация

ВеткаОтветственность
SembaУчастник 1: интерфейс и пользовательский сценарий
NikitaУчастник 2: данные, формула и движок
BakytzhanУчастник 3: каркас, API, AI и интеграция
mainОбщая версия: интерфейс, движок и API/AI; ограничения указаны выше

Работайте в своей ветке. Сембе после сохранения незакоммиченных изменений нужно подтянуть общую версию, затем подключать src/lib/organizer-api.ts:

git fetch origin
git switch Semba
git merge origin/main

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

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

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

Bakytzhan Kassymgali 18Nikita 13Semba667 7

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

  • 2026-09-23 18:01merge: include Semba jury guide in shared main versionBakytzhan Kassymgali
  • 2026-09-23 18:00merge: include Semba jury guide in shared main versionBakytzhan Kassymgali
  • 2026-09-23 17:59merge: preserve main imported snapshot ancestryBakytzhan Kassymgali
  • 2026-09-23 17:58docs: record verified main integration and remaining UI workBakytzhan Kassymgali
  • 2026-09-23 17:58docs: add complete README and jury launch guideSemba667
  • 2026-09-23 17:56chore: import Bakytzhan snapshot 710d106 into mainNikita
  • 2026-09-23 17:55merge: integrate latest Semba interface for main handoffBakytzhan Kassymgali
  • 2026-09-23 17:41chore: finalize organizer API handoff and verification reportBakytzhan Kassymgali
Все коммиты (38)
  • 2026-09-23 17:41feat(ui): adopt civic dashboard style and contextual rule hintsSemba667
  • 2026-09-23 17:37feat(ai): explain verified simulation facts in Russian Kazakh and EnglishBakytzhan Kassymgali
  • 2026-09-23 17:18feat(api): connect event replacement flows and organizer clientBakytzhan Kassymgali
  • 2026-09-23 17:17fix(ui): polish demo interactions after integrationSemba667
  • 2026-09-23 17:12feat(api): integrate organizer engine and live simulationBakytzhan Kassymgali
  • 2026-09-23 17:01chore: remove hosted CI and retain local verificationBakytzhan Kassymgali
  • 2026-09-23 17:01Verify mandatory action edge cases and document integrationNikita
  • 2026-09-23 16:52Add mandatory catalog action opportunity and replacement rankingNikita
  • 2026-09-23 16:46ci: verify integrated mock demo on pushes and pull requestsBakytzhan Kassymgali
  • 2026-09-23 16:46docs: document integrated demo setup and verificationBakytzhan Kassymgali
  • 2026-09-23 16:26merge: integrate verified bootstrap into SembaBakytzhan Kassymgali
  • 2026-09-23 15:59test: add bootstrap browser checks and verification reportBakytzhan Kassymgali
  • 2026-09-23 15:59fix(api): isolate mock responses and expand adapter checksBakytzhan Kassymgali
  • 2026-09-23 15:55Verify all cancellation targets and document general event handoffNikita
  • 2026-09-23 15:49Generalize cancellation to any selected catalog actionNikita
  • 2026-09-23 15:43fix(ui): validate stored plans and reset async stateSemba667
  • 2026-09-23 15:41Revalidate M7 replacements and document engine integrationNikita
  • 2026-09-23 15:36Add isolated M7 cancellation preview and ranked replacementsNikita
  • 2026-09-23 15:27Fix engine validation of malformed data and duplicate costsNikita
  • 2026-09-23 15:24fix(ui): restore valid UTF-8 dashboard sourceSemba667
  • 2026-09-23 15:17feat(ui): event comparisonSemba667
  • 2026-09-23 15:16feat(api): add strict JSON request parsingBakytzhan Kassymgali
  • 2026-09-23 15:14feat(api): serve catalog and validate requestsBakytzhan Kassymgali
  • 2026-09-23 15:10shared-contract-v1Bakytzhan Kassymgali
  • 2026-09-23 15:07Document organizer model and update team promptsNikita
  • 2026-09-23 15:07Align simulation engine with organizer datasetNikita
  • 2026-09-23 15:06feat(ui): base simulationSemba667
  • 2026-09-23 14:41Add event previews and deterministic replacementsNikita
  • 2026-09-23 14:37Implement deterministic plan validation and scoringNikita
  • 2026-09-23 14:29Add Akim project starter packageNikita
Структура репозитория (99 файлов)
.env.example
.gitignore
AGENTS.md
README.md
START-PACKAGE-README.md
docs/BRIEF.md
docs/CONTRACT.md
docs/DATASET.md
docs/DEMO.md
docs/MODEL.md
docs/ORGANIZER-INTEGRATION.md
docs/TECHNICAL-SOURCES.md
eslint.config.mjs
next-env.d.ts
next.config.ts
package-lock.json
package.json
playwright.api.config.ts
playwright.config.ts
postcss.config.mjs
prompts/00-bootstrap.md
prompts/01-ui.md
prompts/02-engine.md
prompts/03-api-ai-integration.md
src/app/api/.gitkeep
src/app/api/catalog/route.ts
src/app/api/events/confirm/route.ts
src/app/api/events/preview/route.ts
src/app/api/explain/route.ts
src/app/api/simulate/route.ts
src/app/globals.css
src/app/layout.tsx
src/app/page.tsx
src/components/.gitkeep
src/contracts/index.ts
src/contracts/organizer-api.ts
src/contracts/organizer.ts
src/data/catalog.json
src/data/organizer-catalog.json
src/data/team-events.ts
src/features/.gitkeep
src/features/dashboard/SimulationDashboard.tsx
src/features/dashboard/stored-plan.ts
src/lib/client-api.ts
src/lib/organizer-api.ts
src/lib/server/.gitkeep
src/lib/server/explanation-templates.ts
src/lib/server/explanation.ts
src/lib/server/organizer-catalog.ts
src/lib/server/organizer-events.ts
src/lib/server/organizer-http.ts
src/lib/server/organizer-request-schemas.ts
src/lib/server/read-json-request.ts
src/lib/server/request-schemas.ts
src/lib/simulation/.gitkeep
src/lib/simulation/event-types.ts
src/lib/simulation/event-utils.ts
src/lib/simulation/events.ts
src/lib/simulation/index.ts
src/lib/simulation/opportunity.ts
src/mocks/catalog.json
src/mocks/event.confirm.json
src/mocks/event.preview.json
src/mocks/explain.template.json
src/mocks/opportunity.confirm.json
src/mocks/opportunity.preview.json
src/mocks/organizer/scenarios.json
src/mocks/requests.json
src/mocks/simulate.invalid-four.json
src/mocks/simulate.invalid-six.json
src/mocks/simulate.valid.json
tests/api/catalog.test.ts
tests/api/client-api-http.test.ts
tests/api/client-api.test.ts
tests/api/organizer-client.test.ts
tests/api/organizer-events.test.ts
tests/api/organizer-explain.test.ts
tests/api/organizer-fixtures.test.ts
tests/api/organizer-simulate.test.ts
tests/api/read-json-request.test.ts
tests/api/request-schemas.test.ts
tests/e2e/.gitkeep
tests/e2e/bootstrap.spec.ts
tests/e2e/mock-dashboard.spec.ts
tests/http/organizer.spec.ts
tests/simulation/.gitkeep
tests/simulation/cancellation.test.mjs
tests/simulation/engine.test.mjs
tests/simulation/events.test.mjs
tests/simulation/opportunity.test.mjs
tests/simulation/validation.test.mjs
tsconfig.json
verification/RESULTS.txt
verification/check-fixtures.mjs
verification/fixture-literals.ts
verification/generate-organizer-mocks.mjs
verification/golden-summary.json
verification/typecheck-fixtures.ts
vitest.config.ts
Ветки (4)

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

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

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