AAYMA
RU
Войти

Юный Аким

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

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

О проекте

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

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

Суть

Изометрическая городская игра: игрок-аким ходит по 5 районам Астаны, выбирает 5 проектов из 14 по 5 направлениям в пределах бюджета 100 у.е. и видит изменение 10 показателей и итоговый Quality of Life Score.

Как устроено

TypeScript-движок проверяет бюджет, повторы, несовместимости и лимит «не более двух мер одного направления», затем считает показатели районов с лагом, побочными эффектами и синергиями. Индекс: Score = 0.7×D_avg + 0.3×D_min − N_crit. Советник полным перебором ищет лучшую замену одного решения. LLM (Anthropic, затем OpenAI, при недоступности шаблон) только объясняет уже рассчитанную сводку, Score не вычисляет. API /api/scenario, /api/improve и /api/explain пересчитывают результат на сервере.

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

  • weighted QoL score
  • lag and synergy effects
  • constraint validation
  • exhaustive single-swap search
  • grounded LLM explanation
  • template fallback
  • independent fixture cross-check

Метрики

Демо-сценарий: Score 52.56 → 56.54 (+3.99), после замены 57.21; 23 сценария кросс-проверки и 73 проверки советника

Особенности

Движок сверен с независимым пакетом фикстур другого участника (100% совпадение). Воспроизводимый сценарий для жюри с точными ожидаемыми числами. Интерфейс на трёх языках. При изменении плана устаревшие советы и объяснения сбрасываются.

Стек

TypeScript · Next.js 16 · React 19 · Tailwind CSS 4 · Canvas · SVG · Python

Модели

OpenAI gpt-4o · Anthropic claude-sonnet-5


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

README

README.md

Юный Аким

Учебный AI-симулятор управления городом команды Tofifidrinkers для HackAlem AI, спец-трек Astana Innovations, кейс «Аким на 5 часов».

1. Идея и задача

Как распределить ограниченный городской бюджет, чтобы улучшить жизнь жителей и не оставить слабые районы без внимания? «Юный Аким» позволяет попробовать себя в роли акима: изучить районы, выбрать пять проектов и увидеть последствия для качества жизни.

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

Это учебная модель на синтетических данных кейса. Она не прогнозирует реальные последствия для Астаны и не заменяет экономическую экспертизу.

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

  • Игровая изометрическая карта пяти районов: Есиль, Алматы, Сарыарка, Байконур и Нура. Персонажем можно управлять стрелками, WASD, экранными кнопками или выбирать маршрут кликом; местные проекты доступны в районах, общегородские — в акимате.
  • Каталог из 14 мероприятий по пяти направлениям: транспорт, экология, соцсфера, безопасность и сервисы.
  • Фиксированный бюджет 100 условных единиц и план из ровно пяти решений.
  • Проверка бюджета, повторов, района применения, несовместимостей и ограничения «не более двух мер одного направления».
  • Расчёт десяти показателей для каждого района с учётом задержки эффекта, побочных эффектов и синергий.
  • Сравнение исходного и итогового состояния, общий Astana Quality of Life Score, худший район и показатели ниже критического порога.
  • Интерфейс игры на русском, казахском и английском; смена языка сохраняет текущий план. AI-текст пока запрашивается на русском.
  • Анализ расходов и последствий по районам, показ побочных эффектов и предупреждение о концентрации бюджета.
  • Советник, который ищет лучшую допустимую замену одного решения, показывает эффект и позволяет применить её.
  • Объяснение рассчитанного результата через OpenAI или Anthropic API. Если ключ не задан или провайдер недоступен, возвращается явно обозначенное объяснение по шаблону.
  • Защита интерфейса от устаревших ответов: изменение плана сбрасывает предыдущие советы и объяснения.

Основной игровой сценарий доступен на / и /game. В игре суммы отображаются в предложенном учебном масштабе: 1 условная единица = 10 млн ₸, бюджет = 1 млрд ₸. Интерфейс отмечает, что масштаб требует согласования и не является реальной сметой; движок продолжает считать в исходных 100 условных единицах.

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

  1. Пользователь открывает сайт и знакомится с исходными показателями районов.
  2. Посещает районы и акимат, выбирает проекты и формирует план из пяти решений в пределах бюджета.
  3. Общий расчётный движок проверяет правила. При недопустимом плане интерфейс объясняет причину.
  4. Для допустимого плана рассчитываются значения показателей и итоговый индекс. Интерфейс показывает сравнение с базой.
  5. По запросу советник перебирает допустимые замены одного решения и предлагает вариант с более высоким индексом.
  6. По запросу AI получает рассчитанную сводку, каталог, ограничения и проверенную замену; объясняет сильные стороны, риски и рекомендации. Источник ответа отображается в интерфейсе.

Как считается индекс

Score = 0.7 × D_avg + 0.3 × D_min − N_crit
  • D_avg — средняя оценка районов с учётом долей населения.
  • D_min — оценка самого слабого района.
  • N_crit — количество пар «район — показатель» со значением ниже 40.
  • Оценка района — взвешенная сумма его десяти показателей.
  • Эффекты мероприятий учитывают лаг; синергии добавляются по правилам датасета; итоговые показатели ограничены диапазоном 0–100.

Округление выполняется при отображении. Языковая модель не вычисляет Score и не выбирает числовой результат: расчёт и поиск замены выполняет TypeScript-код.

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

КомпонентРеализация
ЯзыкTypeScript
Веб-приложение и серверNext.js 16.3.6, App Router, Node.js
ИнтерфейсReact 19.2.8, Tailwind CSS 4, CSS, SVG и Canvas
AIПрямые серверные HTTP-запросы через fetch к OpenAI Chat Completions API и Anthropic Messages API
ПроверкиTypeScript, ESLint 9, tsx, Python 3 для независимых и HTTP-проверок
Хранение данныхСтатические TypeScript/JSON-файлы; отдельной базы данных нет

Модели задаются переменными окружения. Текущие значения по умолчанию в коде: OPENAI_MODEL=gpt-4o и ANTHROPIC_MODEL=claude-sonnet-5. Это строки конфигурации, а не подтверждение доступности моделей конкретному аккаунту. Для живого запуска задайте доступную вашему ключу модель, совместимую с используемым API.

5. Архитектура

Фронтенд и сервер находятся в одном репозитории и одном Next.js-приложении.

Интерфейс → выбранные решения → общий движок → показатели и Score
                           ↓
                    серверные API
                    ├─ /api/scenario → проверка и расчёт
                    ├─ /api/improve  → поиск одной замены
                    └─ /api/explain  → пересчёт → сводка → LLM / шаблон
Файл / каталогОтветственность
src/lib/data.tsРайоны, показатели, мероприятия, веса, бюджет, совместимость и синергии
src/lib/engine.tsВалидация, исходное состояние и расчёт сценария
src/lib/improve.tsПоиск замены через общий движок, без копирования формулы
src/lib/explain.tsПодготовка фактов для AI, вызовы провайдеров и резервный шаблон
src/app/api/Серверные обработчики; результат пересчитывается на сервере
src/components/game/Игровая карта, перемещение, выбор проектов, три языка и анализ последствий
src/components/game/renderWorld.ts, src/components/pixelSprites.tsОтрисовка игровой карты и спрайтов
fixtures/daniyal/Независимый проверочный комплект

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

Требования

  • Node.js 20.9 или новее, npm и Git.
  • Доступ к репозиторию, если он остаётся приватным.
  • Python 3 — только для дополнительных проверок.
  • Сеть для установки зависимостей; первая сборка может обращаться к Google Fonts через next/font/google.

Локальный запуск

git clone https://github.com/BAITC-Hacks/hack-f9ef362b-tofifidrinkers.git
cd hack-f9ef362b-tofifidrinkers
npm ci
npm run dev

Откройте http://localhost:3000. Если порт занят, используйте адрес из вывода сервера.

Подключение AI

Без ключей работают расчёт, советник и шаблонное объяснение. Для ответа модели создайте в корне файл .env.local и настройте один из провайдеров:

# Вариант 1: OpenAI
OPENAI_API_KEY=ваш_ключ
OPENAI_MODEL=gpt-4o

# Вариант 2: Anthropic
# ANTHROPIC_API_KEY=ваш_ключ
# ANTHROPIC_MODEL=идентификатор_доступной_модели

После изменения окружения перезапустите сервер. Ключи используются только на сервере; .env.local не следует добавлять в Git. На хостинге задайте эти переменные в настройках окружения.

Если настроены оба провайдера, сервер сначала пробует Anthropic, затем OpenAI. Ожидание каждого ограничено восемью секундами; после неудачи доступных провайдеров используется шаблон. Необходимы действующий ключ, доступ к выбранной модели и сеть.

Производственный режим

npm run build
npm run start

7. Проверка решения жюри

Воспроизводимый сценарий

  1. Откройте главную страницу и нажмите «Загрузить пример».
  2. В плане окажутся M7, M8 и M10 в Нуре, M12 для всего города и M5 в Сарыарке.
  3. Проверьте результат:
ЗначениеОжидаемый результат
Стоимость95 из 100 условных единиц; в игре — 950 млн ₸ из 1 млрд ₸
Исходный Score52.55768 → на экране 52.56
Итоговый Score56.54307 → на экране 56.54
Рост относительно базы3.98539 → на экране +3.99
СинергияM10 + M12 в Нуре
  1. В разделе «Последствия» нажмите «Найти улучшение». Ожидаемая замена: M5 в Сарыарке → M3 в Нуре.
  2. Примените замену: стоимость станет 100 условных единиц (в игре 1 млрд ₸), Score — 57.20556 (на экране 57.21), прирост относительно предыдущего плана — +0.66.
  3. Нажмите «Объяснить результат» и проверьте подпись источника. Ответ модели на русском открывается в отдельном блоке; денежные абзацы скрываются, чтобы не смешивать условные единицы и отображаемые тенге. Финансовые значения приведены в таблице анализа. openai или anthropic в ответе API означает ответ соответствующего провайдера; offline-template означает резервный шаблон.
  4. Измените план: предыдущие рекомендации и объяснение должны исчезнуть, а результат — соответствовать новому набору решений.

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

Из корня проекта:

npm run verify
npm run verify:daniyal
npm run verify:improve
npm run verify:explain
npx tsx --test src/components/game/world.test.ts
npm run lint
npm run build
npx tsc --noEmit
python3 fixtures/daniyal/verify_fixtures.py
  • verify проверяет контрольные расчёты и нарушения правил.
  • verify:daniyal сверяет движок с 23 сценариями, базой и шестью граничными проверками.
  • verify:improve содержит 73 проверки советника.
  • verify:explain проверяет контекст, ответы смоделированного провайдера, резервный режим и тайм-аут. Он не подтверждает доступность настоящей модели.

При запущенном сервере в другом терминале:

python3 fixtures/daniyal/verify_http.py http://127.0.0.1:3000

Для проверки резервного объяснения на сервере без AI-ключей:

python3 fixtures/daniyal/verify_http.py http://127.0.0.1:3000 --offline-explanation

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

Источник исходных значений — предоставленный для кейса документ «Датасет районов.docx», указанный в src/lib/data.ts. Числа закреплены в коде и проверочных JSON-файлах. В модели пять районов, десять показателей и четырнадцать мероприятий.

Приложение не получает актуальную городскую статистику и не подключено к муниципальным информационным системам. Карты схематические, без географического API.

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

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

  • Данные синтетические и фиксированные; реальная точность прогноза не оценивалась.
  • Советник ищет улучшение одной заменой, а не глобальный оптимум всех пяти решений. Отсутствие совета не доказывает оптимальность плана.
  • Сценарий хранится в состоянии открытой страницы и сбрасывается при перезагрузке. Нет аккаунтов, базы данных и библиотеки сохранённых сценариев.
  • Реальный AI требует отдельно настроенного окружения. По содержимому репозитория нельзя подтвердить, что ключи уже установлены или вызовы модели успешны.
  • Свободный текст модели может содержать неточности; эталонные числа находятся в расчётном результате.
  • Текущий серверный промпт запрашивает объяснение на русском языке.
  • Расчёт использует условные единицы. Масштаб их отображения в тенге в игре предложен, но не согласован; это не реальные сметы.
  • Это MVP хакатона; нагрузочное тестирование и эксплуатационные гарантии не представлены.

10. Развёрнутая версия

Подтверждённая публичная ссылка в проверенной основной версии репозитория не указана. Для проверки используйте локальный запуск выше. Публикация командой на Netlify находится в процессе настройки. Адрес localhost доступен только на компьютере, где запущен сервер, и не является deployed-версией.

После публикации сюда следует добавить фактический адрес сайта и проверить на нём контрольный сценарий и источник AI-объяснения.

11. Материалы проекта

Название проекта для подачи — «Юный Аким». В текущем интерфейсе и метаданных также используется название кейса «Аким на 5 часов».

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

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

t1esta 9Дилара Ногаева 8ilyas 8Dilkaa 1

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

  • 2026-09-23 17:48Merge pull request #9 from BAITC-Hacks/feature/final-advisor-reportDilkaa
  • 2026-09-23 17:48Document integration with current mainДилара Ногаева
  • 2026-09-23 17:48Merge pull request #8 from BAITC-Hacks/docs/young-akim-readmet1esta
  • 2026-09-23 17:47Merge remote-tracking branch 'origin/main' into feature/final-advisor-reportДилара Ногаева
  • 2026-09-23 17:47Integrate final game, remove legacy interface and update jury READMEt1esta
  • 2026-09-23 17:46Add grounded multilingual final advisor report to city gameДилара Ногаева
  • 2026-09-23 17:45Merge remote-tracking branch 'origin/main'ilyas
  • 2026-09-23 17:45Сделать новый игровой интерфейс (PR #7, canvas-карта, 3 языка) главной страницейilyas
Все коммиты (26)
  • 2026-09-23 17:44Merge pull request #7 from BAITC-Hacks/feature/resident-friendly-gamet1esta
  • 2026-09-23 17:44Paint city immediately after canvas initialization and resizet1esta
  • 2026-09-23 17:32docs: remove obsolete team assignments and optional Claude filest1esta
  • 2026-09-23 17:26docs: prepare Russian jury README for Юный Акимt1esta
  • 2026-09-23 17:16Make city game accessible to residents with screen-axis movement and three languagesДилара Ногаева
  • 2026-09-23 16:59Add playable isometric city game with budget and real scenario outcomesДилара Ногаева
  • 2026-09-23 16:18Integrate team UI and validation; connect city results and ground AI explanationst1esta
  • 2026-09-23 15:55Add code-only pixel art district board and scenario previewДилара Ногаева
  • 2026-09-23 15:42Reject malformed scenario inputs before calculation; add HTTP regression checkst1esta
  • 2026-09-23 15:42Прототип игровой визуализации: доска районов (/board)ilyas
  • 2026-09-23 15:40Превратить интерфейс в городскую игру с акимом и посещением районовДилара Ногаева
  • 2026-09-23 15:27Добавить демо-сценарий и безопасное применение рекомендаций в интерфейсеДилара Ногаева
  • 2026-09-23 15:10Добавить npm run verify:improve в package.jsonilyas
  • 2026-09-23 15:04Реализовать советник одной замены и 73 проверки Даниялаt1esta
  • 2026-09-23 14:45improve.ts: точный алгоритм и tie-break из IMPROVEMENT_SPEC.md, добавлено costDeltailyas
  • 2026-09-23 14:44Кросс-проверка с пакетом Данияла: коды ошибок, фикс пустого сценария, 100% совпадениеilyas
  • 2026-09-23 14:35Merge organizer's initial repo README with project READMEilyas
  • 2026-09-23 14:20MVP симулятора: движок расчёта, валидатор, AI-объяснение (OpenAI), заглушка улучшенияilyas
Структура репозитория (47 файлов)
.gitignore
AGENTS.md
README.md
eslint.config.mjs
fixtures/daniyal/city-data.json
fixtures/daniyal/scenario-fixtures.json
fixtures/daniyal/verify_fixtures.py
fixtures/daniyal/verify_http.py
next.config.ts
package-lock.json
package.json
postcss.config.mjs
src/app/api/explain/route.ts
src/app/api/improve/route.ts
src/app/api/scenario/route.ts
src/app/favicon.ico
src/app/game/page.tsx
src/app/globals.css
src/app/layout.tsx
src/app/page.tsx
src/components/game/FINAL_REPORT.md
src/components/game/FinalReport.tsx
src/components/game/Game.tsx
src/components/game/ImpactAnalysis.tsx
src/components/game/WorldCanvas.tsx
src/components/game/game.module.css
src/components/game/i18n.ts
src/components/game/presentation.ts
src/components/game/renderWorld.ts
src/components/game/reportText.ts
src/components/game/useGame.ts
src/components/game/useLocale.ts
src/components/game/world.test.ts
src/components/game/world.ts
src/components/pixelSprites.ts
src/lib/data.ts
src/lib/engine.ts
src/lib/explain.ts
src/lib/finalReport.test.ts
src/lib/finalReport.ts
src/lib/improve.ts
src/lib/reportContract.ts
src/lib/verify-daniyal.ts
src/lib/verify-explain.ts
src/lib/verify-improve.ts
src/lib/verify.ts
tsconfig.json

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

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

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