AAYMA
RU
Войти

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

Городской симулятор: пользователь выбирает 5 из 14 мероприятий в бюджете 100 единиц, а система считает показатели по пяти районам и Astana Quality…

Рабочий MVP
Команда «DG» 4💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: DG
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Рабочий MVP

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

Суть

Городской симулятор: пользователь выбирает 5 из 14 мероприятий в бюджете 100 единиц, а система считает показатели по пяти районам и Astana Quality of Life Score с AI-объяснением.

Как устроено

Данные о районах, мероприятиях и правилах (лимиты, веса, синергии, несовместимости) лежат в локальных JSON. FastAPI-валидатор проверяет сценарий: ровно 5 мер, не больше 2 на направление, бюджет не превышен. Детерминированный движок применяет эффекты с учётом лагов и синергий, ограничивает показатели диапазоном 0–100 и считает Score по среднему с весом населения, слабейшему району и штрафу за значения ниже 40. Готовые числа передаются в Claude Sonnet 4.6 для текстового объяснения; без ключа используется шаблонный fallback.

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

  • deterministic scoring engine
  • lag scaling
  • synergies/incompatibilities rules
  • population-weighted score
  • template fallback

Особенности

LLM отделён от расчёта: Claude только объясняет уже посчитанный результат, а при отсутствии API работает шаблонный fallback. История коммитов при этом хаотичная: много коммитов «Add files via upload», создание и удаление папок.

Стек

Python · FastAPI · Uvicorn · Pydantic · HTML · CSS · JavaScript · Anthropic SDK · pytest

Модели

Claude Sonnet 4.6


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

README

README.md

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

Симулятор управленческих решений для Астаны. Пользователь выбирает пять городских мероприятий в рамках виртуального бюджета и видит, как выбранный набор меняет расчётный Astana Quality of Life Score, показатели районов и число критических значений.

Проблема и для кого

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

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

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

  • Каталог из 14 мероприятий по направлениям транспорта, экологии, социальной сферы, безопасности и городских сервисов.
  • Выбор ровно пяти мероприятий при бюджете не более 100 условных единиц.
  • Выбор района для районных мероприятий; городские мероприятия применяются ко всем районам.
  • Проверка лимита не более двух мер на направление, повторов и заданных несовместимостей.
  • Детерминированный расчёт показателей по пяти районам с учётом лагов мероприятий и заданных синергий.
  • Расчёт Astana Quality of Life Score, вклада районов и слабейшего района, стоимости сценария и показателей ниже порога 40.
  • Экран результатов с визуальным сравнением показателей «до / после», сработавшими синергиями, критическими значениями и текстовым объяснением.
  • Сравнение рассчитанных сценариев в текущей сессии браузера.
  • Офлайн-объяснение по шаблонам, если Anthropic API недоступен или ключ не задан.

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

  1. Интерфейс загружает список мероприятий и районов из backend API.
  2. Пользователь выбирает пять мероприятий, указывает районы для районных мер и укладывается в бюджет.
  3. Frontend отправляет запрос POST /api/simulate со списком решений.
  4. Backend проверяет входные данные. Если сценарий допустим, расчётный движок применяет эффекты мероприятий, масштабирует их с учётом лага, добавляет предусмотренные синергии и ограничивает показатели диапазоном 0–100.
  5. Для каждого района вычисляется взвешенный показатель. Общий Score учитывает средний результат по населению, слабейший район и штраф за каждый показатель ниже 40.
  6. Готовые числовые результаты передаются модулю объяснений. Он обращается к Anthropic Claude при наличии переменной окружения ANTHROPIC_API_KEY, иначе формирует шаблонный текст.
  7. Интерфейс показывает итог, разницу с базовым сценарием, показатели районов и объяснение.

AI-модуль объясняет уже рассчитанные результаты и не выполняет числовой расчёт Score.

Технологии

  • Python — backend и расчётная модель.
  • FastAPI, Uvicorn, Pydantic — HTTP API, запуск ASGI-сервера и проверка структуры запросов.
  • HTML, CSS, JavaScript без отдельного frontend-фреймворка — пользовательский интерфейс.
  • Anthropic Python SDK и модель Claude Sonnet 4.6 (claude-sonnet-4-6) — необязательное текстовое объяснение.
  • JSON — локальные исходные данные районов, мероприятий и правил.
  • pytest — зависимость и тесты расчётного движка.

Список Python-зависимостей находится в Backend/requirements.txt.

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

Frontend/
  index.html       разметка интерфейса
  style.css        оформление
  app.js           загрузка данных, выбор мер и отображение результатов

Backend/
  api/main.py      HTTP API на FastAPI
  engine/
    data_loader.py чтение файлов с исходными данными
    validator.py   проверка сценария и правил
    calculator.py  детерминированный расчёт
    calculator_test.py тесты расчётного движка
  ai/explainer.py  объяснение готового результата через Anthropic или fallback
  data/
    districts.json районы и исходные показатели
    activities.json каталог мероприятий и эффекты
    rules.json     бюджет, лимиты, веса, синергии и несовместимости

data.py            отдельный Python-модуль с исходными данными

Поток запроса:

flowchart LR
    U[Пользователь] --> F[Frontend HTML/CSS/JS]
    F -->|HTTP JSON| A[FastAPI]
    A --> V[Валидация сценария]
    V --> C[Расчётный движок]
    D[(Локальные JSON-файлы)] --> V
    D --> C
    C -->|Готовые числа| X[AI-объяснение или fallback]
    X --> A
    A -->|Результат JSON| F

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

Требуются Python 3.10 или новее и Git. Все команды выполняются из корня репозитория.

1. Получите проект и установите зависимости

git clone https://github.com/BAITC-Hacks/hack-2e344b51-dg.git
cd hack-2e344b51-dg
python -m venv .venv

Активируйте виртуальное окружение:

Linux/macOS

source .venv/bin/activate

Windows PowerShell

.venv\Scripts\Activate.ps1

Установите зависимости:

python -m pip install -r Backend/requirements.txt

2. (Необязательно) включите объяснение через Anthropic

Без ключа приложение использует встроенный fallback и может работать без вызова AI API.

Linux/macOS

export ANTHROPIC_API_KEY="ваш-ключ"

Windows PowerShell

$env:ANTHROPIC_API_KEY = "ваш-ключ"

3. Запустите backend

uvicorn Backend.api.main:app --reload --port 8000

API будет доступен по адресу http://localhost:8000, интерактивная документация — http://localhost:8000/docs.

4. Запустите интерфейс

В отдельном терминале из корня репозитория выполните:

python -m http.server 5500 --directory Frontend

Откройте http://localhost:5500. Интерфейс по умолчанию обращается к backend на http://localhost:8000.

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

Проверка через интерфейс

  1. Запустите backend и frontend по инструкции выше.
  2. Откройте http://localhost:5500.
  3. Выберите пять допустимых решений, например:
    • M1 — выделенные полосы для автобусов, район Есиль;
    • M2 — умные светофоры;
    • M8 — центр семейного здоровья / поликлиника, район Нура;
    • M10 — освещение и камеры, район Нура;
    • M12 — единая цифровая платформа обращений.
  4. Общая стоимость этого набора — 86 из 100. Нажмите «Рассчитать сценарий».
  5. Убедитесь, что появились Score, сравнение с базовым сценарием, показатели районов и объяснение. Для пары M1 + M2 должна отображаться заданная в правилах синергия.
  6. Нажмите «Собрать новый сценарий», выберите другой допустимый набор и проверьте таблицу сравнения.

Проверка API запросом

При запущенном backend можно отправить тот же пример напрямую:

curl -X POST http://localhost:8000/api/simulate \
  -H "Content-Type: application/json" \
  -d '{
    "decisions": [
      {"activity_id": "M1", "district_id": "esil"},
      {"activity_id": "M2"},
      {"activity_id": "M8", "district_id": "nura"},
      {"activity_id": "M10", "district_id": "nura"},
      {"activity_id": "M12"}
    ]
  }'

В ответе ожидается JSON с полями score, base_score, districts, total_cost, triggered_synergies, critical_pairs и explanation. Точное значение Score зависит от текущих данных и правил в репозитории.

Тесты расчётного движка

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

python -m pytest Backend/engine/calculator_test.py

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

  • Расчётные данные поставляются вместе с проектом в Backend/data/districts.json, Backend/data/activities.json и Backend/data/rules.json; backend читает их локально.
  • В данных указаны пять районов, десять показателей, доли населения, 14 мероприятий, их стоимость, лаги и эффекты.
  • Правила задают горизонт 8 кварталов, бюджет 100 условных единиц, ровно пять решений, максимум две меры одного направления, веса показателей, синергии и несовместимости.
  • Внешний сервис используется только для текстового объяснения: Anthropic API с моделью Claude Sonnet 4.6, если задан ANTHROPIC_API_KEY.
  • Для локального запуска нужны только Python-зависимости из Backend/requirements.txt. Отдельная база данных, аккаунты и ключи для расчётного движка не используются.

Ограничения текущей версии

  • Значения показателей, стоимость и эффекты мер — статические модельные данные из репозитория; автоматического обновления из городских источников нет.
  • Score отражает заданную формулу и принятые веса, а не подтверждённое измерение качества жизни или фактический прогноз.
  • В приложении можно выбрать только ровно пять мероприятий; бюджет ограничен 100 условными единицами.
  • Сравнение сценариев хранится только в состоянии текущей страницы браузера и не сохраняется между сессиями.
  • AI-объяснение зависит от доступности Anthropic API и действующего ключа. Без них используется шаблонный fallback.
  • API настроен на CORS для любых origin; механизм аутентификации в текущем коде не реализован.

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

Ссылка на deployed-версию в репозитории не указана. Для ознакомления и запуска доступен репозиторий проекта.

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

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

GalGokha 42Dilyara Kurmangazykyzy 31

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

  • 2026-09-23 17:39docs: rewrite README in RussianGalGokha
  • 2026-09-23 17:25Update app.jsGalGokha
  • 2026-09-23 17:19Update README.mdGalGokha
  • 2026-09-23 17:14Update main.pyGalGokha
  • 2026-09-23 16:58Delete requirements.txtGalGokha
  • 2026-09-23 16:58Delete __init__.pyGalGokha
  • 2026-09-23 16:57Delete engine directoryGalGokha
  • 2026-09-23 16:57Delete data directoryGalGokha
Все коммиты (72)
  • 2026-09-23 16:57Delete api directoryGalGokha
  • 2026-09-23 16:56Delete ai directoryGalGokha
  • 2026-09-23 16:44Delete Backend directoryGalGokha
  • 2026-09-23 16:40Create aiGalGokha
  • 2026-09-23 16:40Delete Backend/ai/api/data/engine/__init__.py directoryGalGokha
  • 2026-09-23 16:39Create requirements.pyGalGokha
  • 2026-09-23 16:37Delete backend/ __init__.py api/ __init__.py main.py engine/ __init__.py calculator.py data_loader.py validator.py ai/ __init__.py explainer.py data directoryGalGokha
  • 2026-09-23 16:36Create activities.json districts.json rules.jsonGalGokha
  • 2026-09-23 16:30Delete Backend/__init__.pyGalGokha
  • 2026-09-23 16:28Create __init__.pyGalGokha
  • 2026-09-23 16:28Delete BackendGalGokha
  • 2026-09-23 16:24Create BackendGalGokha
  • 2026-09-23 16:21Delete Frontend/__init__.pyGalGokha
  • 2026-09-23 16:21Add files via uploadGalGokha
  • 2026-09-23 16:15Create FrontendGalGokha
  • 2026-09-23 16:06Delete README.md backend/ data/ engine directoryGalGokha
  • 2026-09-23 16:04Create __init__.py data.py requirements.txtGalGokha
  • 2026-09-23 16:54Add files via uploadDilyara Kurmangazykyzy
  • 2026-09-23 16:54Create __init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 16:53Add files via uploadDilyara Kurmangazykyzy
  • 2026-09-23 16:52Create activities.json with transport and ecology dataDilyara Kurmangazykyzy
  • 2026-09-23 16:51Add files via uploadDilyara Kurmangazykyzy
  • 2026-09-23 16:50Add files via uploadDilyara Kurmangazykyzy
  • 2026-09-23 16:49Initialize FastAPI backend with API endpointsDilyara Kurmangazykyzy
  • 2026-09-23 16:48Add files via uploadDilyara Kurmangazykyzy
  • 2026-09-23 16:48Create __init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 16:47Create __init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 16:47Delete Backend/ai directoryDilyara Kurmangazykyzy
  • 2026-09-23 16:46Delete Backend/__init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 16:46Create __init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 16:45Create __init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 15:43Delete Backend directoryGalGokha
  • 2026-09-23 15:41Create BackendGalGokha
  • 2026-09-23 15:35Delete backendGalGokha
  • 2026-09-23 15:35Create backendGalGokha
  • 2026-09-23 16:34Revise README for project overview and setupDilyara Kurmangazykyzy
  • 2026-09-23 15:23Add files via uploadGalGokha
  • 2026-09-23 15:21Delete validator.pyGalGokha
  • 2026-09-23 15:21Delete engineGalGokha
  • 2026-09-23 15:21Delete data_loader.pyGalGokha
  • 2026-09-23 15:20Delete calculator_test.pyGalGokha
  • 2026-09-23 15:20Delete calculator.pyGalGokha
  • 2026-09-23 16:19Create __init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 16:18Delete FrontendDilyara Kurmangazykyzy
  • 2026-09-23 16:17Delete engine/Frontend directoryDilyara Kurmangazykyzy
  • 2026-09-23 16:17Create __init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 15:15engineGalGokha
  • 2026-09-23 15:10Update engineGalGokha
  • 2026-09-23 15:08Update engineGalGokha
  • 2026-09-23 15:06Create engineGalGokha
  • 2026-09-23 15:06Add files via uploadGalGokha
  • 2026-09-23 16:01Add files via uploadDilyara Kurmangazykyzy
  • 2026-09-23 16:01Create __init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 16:00Add files via uploadDilyara Kurmangazykyzy
  • 2026-09-23 16:00Create __init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 15:41Delete Backend/data directoryDilyara Kurmangazykyzy
  • 2026-09-23 15:41Create __init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 15:26Rename rules.json to data/rules.jsonDilyara Kurmangazykyzy
  • 2026-09-23 15:25Rename activities.json to data/activities.jsonDilyara Kurmangazykyzy
  • 2026-09-23 15:24Rename districts.json to data/districts.jsonDilyara Kurmangazykyzy
  • 2026-09-23 15:22Create __init__.pyDilyara Kurmangazykyzy
  • 2026-09-23 13:58Update README.mdGalGokha
  • 2026-09-23 14:54Add files via uploadDilyara Kurmangazykyzy
  • 2026-09-23 13:57Add files via uploadDilyara Kurmangazykyzy
Структура репозитория (19 файлов)
Backend/__init__.py
Backend/ai/__init__.py
Backend/ai/explainer.py
Backend/api/__init__.py
Backend/api/main.py
Backend/data/activities.json
Backend/data/districts.json
Backend/data/rules.json
Backend/engine/__init__.py
Backend/engine/calculator.py
Backend/engine/calculator_test.py
Backend/engine/data_loader.py
Backend/engine/validator.py
Backend/requirements.txt
Frontend/app.js
Frontend/index.html
Frontend/style.css
README.md
data.py

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

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

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