О проекте
Команда: 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. Как работает решение
- Пользователь открывает сайт и знакомится с исходными показателями районов.
- Посещает районы и акимат, выбирает проекты и формирует план из пяти решений в пределах бюджета.
- Общий расчётный движок проверяет правила. При недопустимом плане интерфейс объясняет причину.
- Для допустимого плана рассчитываются значения показателей и итоговый индекс. Интерфейс показывает сравнение с базой.
- По запросу советник перебирает допустимые замены одного решения и предлагает вариант с более высоким индексом.
- По запросу 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. Проверка решения жюри
Воспроизводимый сценарий
- Откройте главную страницу и нажмите «Загрузить пример».
- В плане окажутся M7, M8 и M10 в Нуре, M12 для всего города и M5 в Сарыарке.
- Проверьте результат:
| Значение | Ожидаемый результат |
|---|---|
| Стоимость | 95 из 100 условных единиц; в игре — 950 млн ₸ из 1 млрд ₸ |
| Исходный Score | 52.55768 → на экране 52.56 |
| Итоговый Score | 56.54307 → на экране 56.54 |
| Рост относительно базы | 3.98539 → на экране +3.99 |
| Синергия | M10 + M12 в Нуре |
- В разделе «Последствия» нажмите «Найти улучшение». Ожидаемая замена: M5 в Сарыарке → M3 в Нуре.
- Примените замену: стоимость станет 100 условных единиц (в игре 1 млрд ₸), Score — 57.20556 (на экране 57.21), прирост относительно предыдущего плана — +0.66.
- Нажмите «Объяснить результат» и проверьте подпись источника. Ответ модели на русском открывается в отдельном блоке; денежные абзацы скрываются, чтобы не смешивать условные единицы и отображаемые тенге. Финансовые значения приведены в таблице анализа.
openaiилиanthropicв ответе API означает ответ соответствующего провайдера;offline-templateозначает резервный шаблон. - Измените план: предыдущие рекомендации и объяснение должны исчезнуть, а результат — соответствовать новому набору решений.
Автоматические проверки
Из корня проекта:
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 часов».
Авторы коммитов
История коммитов
- 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 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.