AAYMA
RU
Войти

that day

Игровой симулятор «Аким на 5 часов» на Next.js.

Доведённый продукт
Команда «that-day-in» 25💬 0 комментариевс 22 сентября 2026 г.

О проекте

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

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

Суть

Игровой симулятор «Аким на 5 часов» на Next.js. Интерактивная SVG-карта Астаны, 14 мер и бюджет 100, серверный расчёт Score, AI-объяснение через Structured Outputs, рекомендации, события на карте, общий рейтинг в Redis и генерация презентации.

Как устроено

Районы, показатели, меры и правила загружаются из синтетического dataset.json. Общий расчётный модуль считает лаги, синергии, критические значения и Score = 0.7×среднее (по населению) + 0.3×минимум − число критических. Клиент передаёт только ID мер и районов, сервер проверяет всё через Zod и пересчитывает сам. Готовые факты уходят в OpenAI Responses API со Structured Outputs за объяснением и обоснованием рекомендаций (замена одной меры). Рейтинг хранится в Upstash Redis, участник определяется подписанной cookie.

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

  • детерминированная модель Score
  • OpenAI Structured Outputs
  • Zod-контракты клиент/сервер
  • замена одной меры
  • события на карте с резервом бюджета
  • лидерборд в Redis
  • Markdown-презентация
  • экспериментальный анализ отзывов

Особенности

Задеплоено на Vercel, есть общий рейтинг участников на Redis. SVG-карта Астаны собрана из сохранённой географии OSM. Интерфейс и сервер делят один расчётный модуль. В README заявлено 143 unit/API и 16 e2e-тестов без трат AI-токенов. Первый коммит сделан 22.09 вечером, это подготовка датасета.

Стек

TypeScript · Next.js 16 · React 19 · Node.js 22 · Tailwind CSS 4 · Zod 4 · OpenAI SDK · Upstash Redis · Vercel · Vitest · Playwright · Python · OpenStreetMap

Модели

gpt-5.4-mini-2026-03-17


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

README

README.md

that day

that day — Аким на 5 часов

AI-симулятор городского управления «Аким на 5 часов». Проект помогает оценить, как решения при ограниченном бюджете влияют на районы Астаны и качество жизни жителей.

Открыть работающий сайт · Документация · Ветки и PR

Проблема и пользователи

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

Симулятор предназначен для городских управленцев, аналитиков и участников хакатона. Он позволяет сравнить варианты на синтетических данных и обосновать выбор. Игровая эстетика используется в интерфейсе; логика решений определяется датасетом.

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

ВозможностьКак работает
Единый стартовый бюджетКаждому участнику доступны собственные 100 виртуальных единиц. Расходы участников независимы
Решения по пяти направлениямКаталог из 14 мероприятий: транспорт, экология, соцсфера, безопасность и сервисы. Можно выбрать район или городское мероприятие, изменить и удалить решение
Контроль допустимостиПроверяются бюджет, количество и уникальность мер, ограничения направлений и несовместимости. Сервер повторно проверяет отправленный сценарий
Интерактивная картаПять районов, достопримечательности, перемещение и масштаб. Выбор района приближает и выделяет его; «Весь город» возвращает общий вид
Изменения показателейСправа от карты показаны 10 показателей района и его индекс до/после решений. Изменения сопровождаются короткими анимациями; в аналитике доступны диаграммы районов
Astana Quality of Life ScoreРасчёт учитывает эффекты мер, задержки, синергии, доли населения и критические значения. AI не назначает баллы
AI-анализСтруктурированное объяснение сильных сторон, рисков и последствий со ссылками на факты расчёта
РекомендацииДо трёх допустимых вариантов замены одного мероприятия с приростом Score, расходами и AI-обоснованием. Вариант можно применить к плану
События на картеОсадки, жара, сбой сервисов и ремонт улиц размещаются на районе или всём городе перетаскиванием либо кликом. До трёх событий одновременно; резерв уменьшает доступный бюджет, удаление возвращает средства
Перераспределение бюджетаОтдельный редактор сценария события позволяет заменить мероприятия и пересчитать план с учётом резерва. Есть случайный выбор события
Сравнение участниковОбщий рейтинг через Redis: явная публикация с именем, личный лучший результат, равные места, выделение своей записи и страницы результатов
Краткая презентацияПросмотр и скачивание Markdown: 9 слайдов с AI, 6 расчётных/служебных слайдов при его недоступности
Сохранение и доступностьЧерновик и последние отчёты сохраняются в браузере. Есть мобильная компоновка, управление картой/событиями с клавиатуры и поддержка уменьшенного движения

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

Также реализован экспериментальный API анализа отзывов: сигналы с цитатами и ограниченный пересчёт показателей. Он не имеет отдельного экрана и исключён из рейтинга.

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

  1. Приложение загружает районы, показатели, мероприятия и правила из синтетического JSON.
  2. На экране «Карта и решения» пользователь выбирает район и составляет план. Слева видны мероприятия и бюджет, в центре — карта, справа — показатели до/после.
  3. По желанию пользователь размещает учебные события и исследует их влияние. События карты учитываются в отдельном предварительном расчёте.
  4. «Рассчитать сценарий» открывает аналитику: сервер проверяет данные, пересчитывает основной план и передаёт готовые факты AI.
  5. Пользователь получает Score и объяснение, сравнивает районы, применяет рекомендацию, публикует результат или формирует презентацию.

События карты не включаются в AI-анализ и рейтинг основного плана. Это отдельный эксперимент; различие обозначено в интерфейсе.

Технологии

ОбластьИспользуется в проекте
ПриложениеTypeScript, Next.js 16, React 19, Node.js 22
ИнтерфейсCSS, Tailwind CSS 4, SVG-карта, Lucide React, шрифт Manrope
Контракты и валидацияZod 4, общие схемы для клиента и сервера
AIOpenAI SDK 6, Responses API, Structured Outputs. Модель по умолчанию — gpt-5.4-mini-2026-03-17; переопределяется через OPENAI_MODEL
ХранениеJSON в репозитории, браузерный localStorage, Upstash-совместимый Redis REST для рейтинга
ПроверкиVitest, Playwright, TypeScript, ESLint
Подготовка данных и картыСкрипты Python, сохранённая география OpenStreetMap
РазмещениеVercel; публикация через CLI

NVIDIA API в текущей реализации не используется.

Архитектура

JSON-датасет → общая расчётная модель → показатели, бюджет и Score
                     ↑                           ↓
Карта и план → API Next.js + проверка Zod → OpenAI → объяснение
                     ↓
               Redis → общий рейтинг

Клиент передаёт идентификаторы мер и районов, а не готовые цены или Score. Сервер проверяет версию каталога и рассчитывает результат самостоятельно. Для быстрого предварительного отображения интерфейс использует тот же расчётный модуль. Ключи OpenAI и Redis остаются на сервере.

Основные компоненты: src/components и src/features — интерфейс и состояние; src/app/api — серверные обработчики; src/lib — расчёты, AI и рейтинг; src/shared — контракты; dataset — входные данные.

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

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

Нужны Node.js 22 и npm. Репозиторий приватный: для клонирования требуется доступ к GitHub команды.

git clone https://github.com/BAITC-Hacks/hack-e54d9694-that-day-in.git
cd hack-e54d9694-that-day-in
git switch main
npm ci
npm run dev

Приложение откроется на http://localhost:3000. Карта, бюджет, Score и события работают без внешних ключей.

Для AI и общего рейтинга скопируйте .env.example в .env.local, если такого файла ещё нет, и заполните серверные переменные:

ПеременнаяДля чего нужна
OPENAI_API_KEYAI-анализ, объяснения рекомендаций и презентации
OPENAI_MODELНеобязательный выбор модели
UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKENОбщее хранилище рейтинга
PARTICIPANT_SECRETПодпись cookie участника; не менее 32 случайных символов

Вместо Upstash-пары поддерживается пара KV_REST_API_URL / KV_REST_API_TOKEN от Vercel Marketplace. Пары нельзя смешивать. Секреты не добавляются в Git и не используют префикс NEXT_PUBLIC_. После настройки перезапустите сервер.

Production-сборка: npm run build, затем npm run start.

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

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

  1. Откройте сайт без активных событий карты.
  2. Нажмите значок помощи в шапке → «Загрузить контрольный пример · 95 ед.».
  3. В плане появятся M7, M8, M10 в Нуре, M12 для всего города и M5 в Сарыарке. Посмотрите показатели выбранного района до/после.
  4. Нажмите «Рассчитать сценарий» и проверьте результат:
ПоказательОжидаемое значение
Расходы / остаток95 / 5
Исходный Score52,55768
Итоговый Score56,54307 — в интерфейсе 56,54
Критических значений после мер0
  1. При доступном OpenAI появится объяснение сильных сторон, рисков и последствий. Затем можно открыть рекомендации, сформировать презентацию или явно опубликовать результат в рейтинге.
  2. Для проверки карты очистите план и удалите активные события. Разместите «Сильные осадки» на Нуре: резерв составит 10, показатель «Разгрузка дорог» изменится 55 → 51. Удалите событие — бюджет и показатели восстановятся.

Расширенный сценарий, включая перераспределение бюджета, — в инструкции демо.

Автоматические проверки

npm run typecheck
npm run lint
npm test
npx playwright install chromium
npm run test:e2e
npm run build

На интегрированной версии от 23.09.2026 проходят 143 unit/API-теста и 16 браузерных сценариев. Автотесты не расходуют AI-токены: платные AI-вызовы и внешний Redis подменяются в тестах; симуляция и события проверяются отдельно. Результаты настоящих проверок внешних сервисов зафиксированы в журнале публикации.

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

  • dataset/dataset.json — заранее подготовленные синтетические данные без реальных персональных данных. Районы, показатели, цены, задержки, синергии и ограничения описаны в датасете.
  • OpenStreetMap — сохранённая география для карты. Внешний картографический API при использовании сайта не требуется. Источники и атрибуция ODbL — в документации карты.
  • OpenAI — текстовое объяснение рассчитанных фактов через структурированные ответы. Версия датасета и ссылки на факты проверяются сервером.
  • Redis — общее хранилище лучших результатов. Участник определяется подписанной cookie браузера.
  • Vercel — размещение приложения и серверного API.

Ограничения

  • Данные и эффекты событий синтетические; пять зон карты условные и не являются официальными административными границами. Результат не является прогнозом реального развития Астаны.
  • Недоступность AI сохраняет численный результат, но текстовое объяснение отсутствует. Проверка структуры и ссылок на факты не гарантирует корректность каждой формулировки модели.
  • Рекомендации ищут улучшения заменой одной меры и не гарантируют глобально лучший сценарий.
  • События карты хранятся только в текущем сеансе страницы и исключены из стандартного AI-отчёта и рейтинга. Мероприятия считаются запланированными: частично выполненные проекты не моделируются.
  • Полноценной авторизации нет. Другой браузер или очистка cookie создают нового участника; локальные черновики и отчёты не синхронизируются между устройствами. Без настроенного Redis общий рейтинг недоступен.
  • Презентация экспортируется в Markdown; PPTX/PDF не реализованы. Для экспериментального API отзывов нет отдельного экрана.

Опубликованная версия и ветки

Демо: akim-five-hours.vercel.app. Код опубликованной сборки и выполненные проверки указаны в docs/deployment.md. Автодеплой GitHub → Vercel пока не подключён: push сам по себе сайт не обновляет.

main — основная версия для запуска и оценки. codex/ui и codex/map-studio — ветки интерфейса и карты; остальные codex/* сохраняют этапы backend и публикации. Названия и история сохранены. Точный статус включения каждой ветки и соответствующие PR — в карте репозитория.

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

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

Bekzat Daulen 31altynbek 28Bekzat Daulen 1

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

  • 2026-09-23 17:50Restore colorful README banner with that day brandingaltynbek
  • 2026-09-23 17:49Restore colorful README banner with that day brandingaltynbek
  • 2026-09-23 17:46Improve readable typography, unify navigation and style presentation slidesBekzat Daulen
  • 2026-09-23 17:44Rewrite that day README for hackathon judging and current featuresaltynbek
  • 2026-09-23 17:41Merge pull request #7 from BAITC-Hacks/codex/map-studioAltynbek
  • 2026-09-23 17:23Document deployed map studio and production checksBekzat Daulen
  • 2026-09-23 17:23Merge remote-tracking branch 'origin/main' into codex/map-studioBekzat Daulen
  • 2026-09-23 17:21Identify active map-studio work separately from integrated stagesaltynbek
Все коммиты (60)
  • 2026-09-23 17:20Add centered map studio with district focus and draggable eventsBekzat Daulen
  • 2026-09-23 17:20Merge remote-tracking branch 'origin/main' into codex/map-studioBekzat Daulen
  • 2026-09-23 17:19Explain codex/deploy stage and link to main applicationaltynbek
  • 2026-09-23 17:19Explain codex/scenario-features stage and link to main applicationaltynbek
  • 2026-09-23 17:19Explain codex/resident-feedback stage and link to main applicationaltynbek
  • 2026-09-23 17:19Explain codex/dataset-prep stage and link to main applicationaltynbek
  • 2026-09-23 17:19Explain codex/contracts stage and link to main applicationaltynbek
  • 2026-09-23 17:18Update README.mdBekzat Daulen
  • 2026-09-23 17:18Merge pull request #3 from BAITC-Hacks/codex/uiAltynbek
  • 2026-09-23 17:17Make main the canonical application branchaltynbek
  • 2026-09-23 17:05Merge remote-tracking branch 'origin/main' into codex/uialtynbek
  • 2026-09-23 17:05Present Akim simulator and document branches on repository homepagealtynbek
  • 2026-09-23 17:04Document project for hackathon judges and map repository branchesaltynbek
  • 2026-09-23 16:52Record updated UI release and verified scenario plus fixBekzat Daulen
  • 2026-09-23 16:50Fix empty scenario plus buttons and verify desktop/mobile interactionsBekzat Daulen
  • 2026-09-23 16:44Redesign city simulator and integrate scenario toolsaltynbek
  • 2026-09-23 16:35Merge remote-tracking branch 'origin/codex/deploy' into codex/uialtynbek
  • 2026-09-23 16:34Record public deployment checks and map performance diagnosisBekzat Daulen
  • 2026-09-23 16:31Preserve nullable scenario fields across Redis leaderboard readsBekzat Daulen
  • 2026-09-23 16:29Handle Upstash empty leaderboard JSON encodingBekzat Daulen
  • 2026-09-23 16:27Support Vercel Marketplace Redis credentials in productionBekzat Daulen
  • 2026-09-23 16:20Prepare integrated hackathon release for Vercel deploymentBekzat Daulen
  • 2026-09-23 16:18Merge remote-tracking branch 'origin/codex/ui' into codex/deployBekzat Daulen
  • 2026-09-23 16:16Merge remote-tracking branch 'origin/codex/scenario-features' into codex/uialtynbek
  • 2026-09-23 16:04Document feature integration, live checks and Redis setupBekzat Daulen
  • 2026-09-23 16:01Implement shared leaderboard API and live AI feature endpointsBekzat Daulen
  • 2026-09-23 15:58Redesign simulator as guided city game with geographic Astana mapaltynbek
  • 2026-09-23 15:50Add feature contracts and deterministic recommendations, events and slidesBekzat Daulen
  • 2026-09-23 15:29Verify live review extraction and bounded city updatesBekzat Daulen
  • 2026-09-23 15:26Add review-driven experimental city state projectionBekzat Daulen
  • 2026-09-23 15:10Connect verified AI reports and document tested simulator designaltynbek
  • 2026-09-23 15:09Merge remote-tracking branch 'origin/codex/dataset-prep' into codex/uialtynbek
  • 2026-09-23 15:05Record compatibility with integrated scenario UIBekzat Daulen
  • 2026-09-23 15:04Merge remote-tracking branch 'origin/codex/ui' into codex/dataset-prepBekzat Daulen
  • 2026-09-23 15:03Verify production HTTP analysis and document backend handoffBekzat Daulen
  • 2026-09-23 15:00Integrate backend simulation and explanation APIsaltynbek
  • 2026-09-23 15:00Connect scenario planning to shared simulation and persist draftsaltynbek
  • 2026-09-23 14:58Merge remote-tracking branch 'origin/codex/ui' into codex/dataset-prepBekzat Daulen
  • 2026-09-23 14:58Add simulate and analyze APIs with grounded explanation-only OpenAIBekzat Daulen
  • 2026-09-23 14:55Integrate authoritative dataset simulation and validationaltynbek
  • 2026-09-23 14:54Build city simulator shell and interactive isometric designaltynbek
  • 2026-09-23 14:53Use source dataset and implement lagged simulation with Score checksBekzat Daulen
  • 2026-09-23 14:50Integrate contracts aligned with authoritative GitHub datasetaltynbek
  • 2026-09-23 14:46Merge remote-tracking branch 'origin/codex/contracts' into codex/dataset-prepBekzat Daulen
  • 2026-09-23 14:46Replace contracts with authoritative dataset rules and explanation-only AIBekzat Daulen
  • 2026-09-23 14:34Record Node 22 verification and integration handoffBekzat Daulen
  • 2026-09-23 14:33Verify catalog contracts and real structured-output model accessBekzat Daulen
  • 2026-09-23 14:31Prepare fixed six-district catalog and model handoffBekzat Daulen
  • 2026-09-23 14:26Define simulator contracts and explicit UI fixturesBekzat Daulen
  • 2026-09-23 14:09Add structured city districts dataset and documentationBekzat Daulen
  • 2026-09-23 10:21Delete .gitignoreAltynbek
  • 2026-09-22 21:33Add gitignorealtynbek
Структура репозитория (113 файлов)
.env.example
.github/pull_request_template.md
.gitignore
.nvmrc
.vercelignore
AGENTS.md
CONTRIBUTING.md
README.md
build_dataset.py
dataset/README.md
dataset/dataset.json
docs/README.md
docs/ai.md
docs/assets/map-studio-desktop.png
docs/assets/map-studio-focused.png
docs/assets/readme-banner.svg
docs/demo.md
docs/deployment.md
docs/features.md
docs/map-studio.md
docs/map.md
docs/model.md
docs/repository.md
docs/ui/choose-decision.png
docs/ui/desktop.png
docs/ui/mobile.png
docs/ui/recommendations.png
eslint.config.mjs
next-env.d.ts
next.config.ts
package-lock.json
package.json
playwright.config.ts
postcss.config.mjs
public/maps/astana-source.json
public/maps/astana.svg
scripts/build-city-map.py
src/app/api/_lib/analyze-handler.ts
src/app/api/_lib/feature-input.ts
src/app/api/_lib/feedback-handler.ts
src/app/api/_lib/leaderboard-handler.ts
src/app/api/_lib/presentation-handler.ts
src/app/api/_lib/recommendations-handler.ts
src/app/api/_lib/scenario.ts
src/app/api/analyze/route.ts
src/app/api/catalog/route.ts
src/app/api/events/preview/route.ts
src/app/api/events/route.ts
src/app/api/events/simulate/route.ts
src/app/api/feedback/recalculate/route.ts
src/app/api/leaderboard/route.ts
src/app/api/presentation/route.ts
src/app/api/recommendations/route.ts
src/app/api/simulate/route.ts
src/app/globals.css
src/app/layout.tsx
src/app/page.tsx
src/app/studio.css
src/components/city-map.tsx
src/components/city-workspace.tsx
src/components/map-studio.tsx
src/components/report-explanation.tsx
src/components/scenario-tools.tsx
src/data/control-scenarios.ts
src/data/events.ts
src/data/index.ts
src/features/map/camera.ts
src/features/map/geography.ts
src/features/map/infrastructure.json
src/features/map/use-playground.ts
src/features/scenario-tools/client.ts
src/features/simulator/use-report.ts
src/features/simulator/use-scenario.ts
src/lib/ai/analyze.ts
src/lib/ai/evidence.ts
src/lib/ai/prompt.ts
src/lib/ai/recommendations.ts
src/lib/ai/reviews.ts
src/lib/competition/identity.ts
src/lib/competition/store.ts
src/lib/feedback/projection.ts
src/lib/simulation/events.ts
src/lib/simulation/index.ts
src/lib/simulation/leaderboard.ts
src/lib/simulation/map-events.ts
src/lib/simulation/presentation.ts
src/lib/simulation/recommendations.ts
src/shared/contracts.ts
src/shared/features-fixtures.ts
src/shared/features.ts
src/shared/feedback-fixtures.ts
src/shared/feedback.ts
src/shared/fixtures.ts
tests/api/features-live-smoke.mjs
tests/api/features.test.ts
tests/api/feedback-live-smoke.mjs
tests/api/feedback.test.ts
tests/api/live-smoke.mjs
tests/api/map-events.test.ts
tests/api/routes.test.ts
tests/e2e/workspace.spec.ts
tests/unit/ai.test.ts
tests/unit/catalog.test.ts
tests/unit/competition.test.ts
tests/unit/contracts.test.ts
tests/unit/features.test.ts
tests/unit/feedback.test.ts
tests/unit/map-events.test.ts
tests/unit/recommendation-ai.test.ts
tests/unit/review-ai.test.ts
tests/unit/simulation.test.ts
tsconfig.json
vitest.config.ts
Ветки (8)

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

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

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