AAYMA
RU
Войти

AKIM: 5 HOURS

Интерактивный симулятор «Аким на 5 часов»: SVG-карта пяти районов, выбор 5 инициатив, Score до/после, советник и эталонная стратегия, найденная…

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

О проекте

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

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

Суть

Интерактивный симулятор «Аким на 5 часов»: SVG-карта пяти районов, выбор 5 инициатив, Score до/после, советник и эталонная стратегия, найденная полным перебором. Интерфейс на EN/RU/KZ.

Как устроено

Официальный датасет проверяется схемой Zod, детерминированный движок без React, сети и случайности считает лаговые эффекты, синергии, баллы районов и итог 0.7×среднее + 0.3×слабейший − критические показатели. Коэффициенты формулы извлекаются из её текста ограниченным парсером без eval. Эталонная стратегия рассчитана офлайн полным перебором (842 790 листьев, 694 395 валидных планов, около 9 с) и закэширована с отпечатком SHA-256 датасета. Советник по умолчанию локальный: жадно ранжирует следующие ходы по реальным проекциям. OpenAI Responses API подключается опционально, его ответы проверяются по схеме и идентификаторам.

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

  • полный перебор
  • детерминированная симуляция
  • Zod-валидация
  • жадный ранжир ходов
  • кэш с SHA-256
  • structured outputs

Метрики

Воспроизведены базовый 52.55768 и пример 56.54307; эталон перебора 57.24 (стоимость 98); 694 395 валидных планов за ≈9.04 с

Особенности

Кэш эталонной стратегии привязан к SHA-256 датасета и перепроверяется при запуске, а коэффициенты формулы разбираются из текста без eval. В README честно объяснено, почему расчёт отличается от эталона организаторов на +0.043 (округление).

Стек

TypeScript · Next.js · React · Zod · pnpm · Vitest · Playwright

Модели

OpenAI (Responses API, модель задаётся в .env)


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

README

README.md

AKIM: 5 HOURS

A better city. Five decisions. Become the akim of Astana, invest a fixed budget, and discover how urban policy changes everyday life.

AKIM combines a deterministic policy engine, an interactive city, and explainable decision support. Every official cost, effect, conflict, and score comes from the supplied dataset and tested code. The LLM does not calculate official scores or numeric effects.

AKIM dashboard

Problem and solution

Urban investments compete for limited resources. A project that improves the city average can still leave its weakest neighborhood behind. AKIM makes these trade-offs visible: five districts, ten indicators, fourteen initiatives, and exactly five decisions.

The main loop is Observe → Decide → Simulate → Understand → Adjust. The player keeps final authority; the advisor supplies a second perspective.

Play locally

Requires Node.js 24+ and pnpm 11.19.0.

pnpm install --frozen-lockfile
pnpm dev

Open http://localhost:3000. The full game and local advisor work without API keys. On a standard Node installation, pnpm can be installed with npm install --global [email protected].

On the supplied workstation, npm is not on PATH. Use its bundled pnpm directly:

node 'C:\Users\Lab-105-Adil\.cache\codex-runtimes\codex-primary-runtime\dependencies\node\node_modules\pnpm\bin\pnpm.cjs' run dev

Production:

pnpm build
pnpm start

No database, Docker, account, or external art download is required. System fonts and locally authored SVG/CSS keep the application self-contained.

Main user flow

  1. Inspect the initial 52.56 quality-of-life score, budget, and critical gaps.
  2. Select a district on the city map or in the district selector.
  3. Read its ten indicators and weakest areas.
  4. Open Initiatives, choose a target, and add actions. Unavailable actions explain their conflicts, budget, or domain constraint.
  5. Watch the score, indicators, budget, visual overlays, and synergies update.
  6. Review your agenda and confirm exactly five valid decisions.
  7. Inspect before/after results and compare with the cached AI Reference Strategy.
  8. Use the advisor and switch between EN / RU / KZ at any time.

Refresh intentionally starts a fresh challenge. There are no saved accounts or sessions.

Hackathon requirements coverage

RequirementImplementationHow to verify
Fixed virtual budgetDataset-driven budget, spending, and remaining balanceHeader → Budget and agenda
Five urban directionsTransport, ecology, social infrastructure, safety, city servicesInitiatives → domain filters
Exactly five decisionsStrict final validator requires five unique choicesHeader counter and Confirm city strategy
Budget/domain/conflict preventionEvery draft is validated before it enters the planAdd an unavailable initiative; its reason is shown
Decisions change indicators and ScoreLagged effects feed district and city projectionsAdd an initiative → live score and indicators update
Final Astana Quality of Life ScorePopulation-weighted average, weakest district, critical-gap penaltyResults → Before → After
Five districtsInteractive keyboard-accessible SVG district mapSelect any district on the map
Official dataset and reproducibilityRuntime Zod validation, locked dependencies, regression and browser testsofficial-dataset.json, pnpm test, pnpm test:e2e
AI analysisOptional server-side OpenAI explanation plus deterministic fallbackAI Advisor → Ask advisor
Strengths, risks, and trade-offsEngine-grounded advisor evidence and result analyticsAI Advisor or Analytics
AI recommendationsCandidate actions are validated and ranked from actual projectionsAI Advisor → Suggested next moves
AI Reference StrategyExhaustive deterministic search, cached after 694,395 valid plansResults → Compare with AI Reference Strategy
Multilingual UISame UI and local advisor in EN, RU, and KZHeader language switch
District visualizationIllustrative five-district map with before/after scoresMain map → Before / After

Architecture

flowchart LR
  Data[Official root JSON] --> Schema[Zod schema + immutable dataset]
  Schema --> Engine[Official deterministic engine]
  UI[React dashboard + SVG city] --> Draft[Validated draft projections]
  Draft --> Engine
  UI --> Final[Strict final confirmation]
  Final --> Engine
  Engine --> Analytics[Indicators, gaps, scores, contributions]
  Analytics --> UI
  Search[Exhaustive deterministic search] --> Engine
  Search --> Cache[Verified reference cache]
  Cache --> UI
  Analytics --> Local[Deterministic fallback advisor]
  Local --> UI
  UI --> API[Server advisor route]
  API --> Engine
  API --> Local
  API --> LLM[Optional OpenAI explanation]
  LLM --> Guard[Schema, identifier and recommendation checks]
  Guard --> UI

The approved simulation engine remains in src/lib/simulation/ and was not rewritten. It has no React, Next.js, network, clock, randomness, or AI dependency.

New planning functions compose its existing validator, effects, and scorer. A draft can be projected before all decisions are chosen, but it is visibly labelled a draft. The official simulatePlan still returns score: null for an incomplete or invalid Governance Challenge. Confirmation always uses that strict function.

Deterministic model

The unmodified root official-dataset.json is the numeric source of truth. Zod validates its shape, finite values, bounds, weight totals, population shares, lag, rule references, and cross-field consistency.

For each initiative:

realized_fraction = (horizon - lag) / horizon
realized_effect = full_effect × realized_fraction
new_indicator = clip(baseline + direct_effects + fixed_synergy_bonuses)
district_score = sum(indicator_weight × new_indicator)
city_average = sum(population_share × district_score)
critical_count = number of district/indicator cells strictly below 40

Score = 0.7 × city_average + 0.3 × weakest_district_score − 1.0 × critical_count

The code reads coefficients and thresholds from the dataset. The final formula is stored as text in the source, so a restricted parser extracts its coefficients without eval. The descriptive baseline/example fields never drive the calculation.

Direct effects are summed in dataset action order, synergies are added once without lag scaling, then values are clipped. Internal precision is retained; UI values are rounded only for display. Consequently, the displayed score delta may differ by a hundredth from subtracting two already-rounded displays.

Reproduced official values

MetricBaselineOfficial example
Esil62.9963.4275
Almaty57.0657.4975
Saryarka54.6556.3
Baikonur56.6357.0675
Nura49.1852.9625
Population-weighted average56.862458.0776
Critical gaps20
Final score52.5576856.54307

The source example costs 95: M7 → Nura, M8 → Nura, M10 → Nura, M12 → City, M5 → Saryarka.

Its calculated result differs from the source's ≈56.5 by +0.04307, consistent with one-decimal rounding. Neither result is hardcoded into the engine.

AI Reference Strategy

The reference is calculated without an LLM. The search enumerates each five-action combination and every district assignment once. It prunes only budget/domain branches that cannot become valid. Every completed candidate reaches the official validator; every valid candidate is scored by the unchanged official simulator.

The completed run examined 842,790 leaf candidates and simulated 694,395 valid plans in approximately 9.04 seconds on this workstation. This is an offline generation step, not a page-load or API request. The result is committed as a derived local JSON cache with a dataset SHA-256 fingerprint. Runtime checks recalculate its validity and score, and tests verify the dataset fingerprint.

The UI accurately labels the result “Best strategy found by exhaustive deterministic search.” This statement applies to the finite official model, not to real-world urban policy.

DecisionTarget
M2 — Adaptive traffic signalsCity
M3 — Light rail expansionNura
M8 — Family health clinicNura
M9 — Neighborhood sports hubsNura
M14 — Utility response teamsCity

Score: 57.236735 → 57.24. Cost: 98. Both critical gaps are closed; Nura remains the weakest district.

pnpm reference:benchmark
pnpm reference:build

The benchmark deliberately stops early and labels its result bounded. Only a completed run writes the exhaustive cache. Do not use that benchmark sample as the reference result.

Advisor architecture

Always-available local advisor

The fallback uses real projections to explain the weakest district, critical gaps, largest improvements, negative consequences, budget, triggered synergies, and player/reference differences.

Next-move suggestions enumerate available action/target pairs, validate them, and rank their actual draft projections by immediate score gain. This greedy ranking is explicitly labelled; it does not claim the best final plan. Alternative comparison independently adds each selected initiative to the current draft. A full plan must be edited before another action can be added.

Optional OpenAI explanations

Copy the environment example only if using external AI:

Copy-Item .env.example .env.local

Set server-side values:

OPENAI_API_KEY=
OPENAI_MODEL=

Choose a model available to your account that supports Responses API structured outputs, then restart the server. There is intentionally no assumed model default. With either value missing, the server returns useful deterministic advice.

The route independently validates the plan and calculates all facts on the server. OpenAI receives those facts, available candidates, alternatives, and the already-calculated reference. It is instructed to explain qualitatively in the chosen language, never calculate or search.

The integration follows the official structured outputs documentation. Responses are checked with Zod. Unsupported recommendation pairs are removed; malformed output, refusals, timeouts, unknown identifiers, or numeric prose trigger the fallback. Numeric cards in the UI always come from the engine. This conservative design can fall back even when a model repeats a correct number, because model prose is not trusted as a numeric source.

The optional live provider path has been smoke-tested through the production Advisor route in EN, RU, and KZ. It remains optional: with either value missing or any provider/schema failure, the route returns the deterministic local advisor. The adapter's response handling, payload, failures, and validation are also covered by mocked HTTP-boundary tests.

Stack and project structure

  • Next.js 16.3.5, React 19.3.0, TypeScript 6.0.3
  • Zod 4.6.5
  • Vitest, ESLint, Playwright, Prettier
  • React state, CSS, locally authored SVG; no game engine
official-dataset.json               Official numeric source
MASTER_SPEC_AKIM_5_HOURS.md          Product and model authority
src/app/                           App shell, styles, advisor route
src/components/                    Dashboard, city, analytics, advisor
src/data/                          Runtime schema, loader, derived reference cache
src/lib/simulation/                Approved official engine (unchanged)
src/lib/planning/                  Draft projections and analytics
src/lib/reference/                 Exhaustive search and cache validation
src/lib/advisor/                   Local advisor and optional OpenAI adapter
src/i18n/                          EN / RU / KK dictionaries
tests/                             Unit and regression tests
e2e/                               Complete browser smoke scenario
scripts/                           Score reporting and reference generation
docs/                              Audits, demo instructions, screenshots

Next.js generated AGENTS.md and CLAUDE.md during development. They are tooling guidance, not product features.

Tests and build

pnpm test
pnpm typecheck
pnpm lint
pnpm build
pnpm test:e2e
pnpm report:scores

Browser tests use installed Google Chrome and start a separate production server on port 3100, with OpenAI configuration explicitly empty. Build first. They cover the entire five-decision flow, a blocked incompatibility, results, reference comparison, no-key advisor, RU/KZ switching, refresh, JavaScript errors, and narrow-screen overflow.

To test an already-running development server:

$env:TEST_BASE_URL = 'http://127.0.0.1:3000'
pnpm test:e2e

The original 73 tests remain unchanged. New tests cover exhaustive enumeration against an independent Cartesian oracle, reference validity and score, draft strictness, suggestions, analytics, translations, advisor contracts, provider failures, and route validation. See the completion report for final counts and gate results.

Reproducible 3–5 minute demo

See the exact demo script. The short path is:

Nura → Initiatives → build the official example → Analytics → confirm → compare with reference → Advisor → RU / KZ.

The Load official example control is a recovery shortcut that loads decisions through the real engine; it does not substitute a fabricated result.

Result and reference comparison

Dataset and security

The supplied Master Spec and root dataset are preserved byte-for-byte. The reference cache is derived, and the map is an illustrative city—not GIS or empirical geography. Scores are outcomes of the supplied hackathon model.

Keys are never accepted from the browser and never included in client props, client bundles, or model context. There is no NEXT_PUBLIC_ key. Requests are size-bounded, schema-validated, checked for matching browser origin/host, and limited to two concurrent external calls per server process. Provider requests time out. React renders text safely; no raw model HTML is inserted.

The project needs no personal data. External calls occur only after the user presses the advisor request button and credentials are configured. Those calls send the question and simulation context to OpenAI. Without credentials, the game has no dependency on an external AI service.

Known limitations and deliberate omissions

  • Refresh resets the challenge and language to the initial state. No saved sessions, accounts, database, or leaderboard.
  • Qualitative OpenAI prose is not a formal guarantee; calculations and displayed numbers remain deterministic. A provider timeout or validation failure returns the local advisor.
  • The local fallback is structured analysis, not a general-purpose conversational model.
  • Next-action suggestions optimize the immediate projection, not all completions of a draft.
  • The illustrative district map uses simplified geometry and symbolic markers; it does not model real buildings or geography.
  • Exhaustive regeneration takes about nine seconds locally. The UI reads the cached result immediately.
  • Kazakh/Russian essential strings are implemented; native-speaker editorial review is advisable before a public release.
  • ESLint 9 is deprecated upstream but matches the current Next.js lint plugins' peer requirements. TypeScript 6 is pinned for their supported range.
  • The API has basic local-demo safeguards, not durable public-service rate limiting or abuse protection.
  • No Sandbox, Crisis Mode, NVIDIA/Brev, authentication, multiplayer, real GIS, WebGL, heavy game engine, complex animations, or presentation generation.

Future work can add persisted local sessions, native-speaker review, more map detail, an authenticated hosted deployment with robust rate limiting, and separately labelled experimental modes. None is necessary for the official challenge demo.

Manual upload

The source package excludes dependencies, builds, caches, traces, and local environment files. Upload the extracted source files, including the root dataset, Master Spec, dotfiles, lockfile, and documentation. Do not upload node_modules, .next, .pnpm-store, or .env.local.

No Git repository was initialized and no GitHub connection, remote repository, or upload was created by this task.

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

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

MeiramAdil 5

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

  • 2026-09-23 17:58Complete AKIM: 5 HOURS hackathon submissionMeiramAdil
  • 2026-09-23 17:47Delete official-dataset.jsonMeiramAdil
  • 2026-09-23 17:46Delete MASTER_SPEC_AKIM_5_HOURS.mdMeiramAdil
  • 2026-09-23 17:46Delete CODEX_START_PROMPT.txtMeiramAdil
  • 2026-09-23 15:31Add files via uploadMeiramAdil
Структура репозитория (67 файлов)
.env.example
.gitignore
.npmrc
AGENTS.md
CLAUDE.md
MASTER_SPEC_AKIM_5_HOURS.md
README.md
docs/COMMANDS.md
docs/DEMO.md
docs/JUDGE_CHECKLIST.md
docs/MILESTONE_1_2_AUDIT.md
docs/P0_COMMANDS.md
docs/P0_COMPLETION.md
docs/screenshots/dashboard.png
docs/screenshots/narrow.png
docs/screenshots/results.png
e2e/governance.spec.ts
eslint.config.mjs
next-env.d.ts
next.config.ts
official-dataset.json
package.json
playwright.config.ts
pnpm-lock.yaml
pnpm-workspace.yaml
scripts/build-reference.ts
scripts/package-submission.ps1
scripts/report-scores.ts
src/app/api/advisor/route.ts
src/app/globals.css
src/app/layout.tsx
src/app/page.tsx
src/components/AdvisorPanel.tsx
src/components/AnalyticsPanel.tsx
src/components/CityMap.tsx
src/components/Dashboard.tsx
src/components/Icon.tsx
src/data/dataset.ts
src/data/reference-cache.json
src/data/schema.ts
src/i18n/en.json
src/i18n/index.ts
src/i18n/kk.json
src/i18n/ru.json
src/lib/advisor/contracts.ts
src/lib/advisor/fallback.ts
src/lib/advisor/service.ts
src/lib/planning/analytics.ts
src/lib/planning/preview.ts
src/lib/reference/cached.ts
src/lib/reference/search.ts
src/lib/simulation/effects.ts
src/lib/simulation/index.ts
src/lib/simulation/score.ts
src/lib/simulation/simulate.ts
src/lib/simulation/types.ts
src/lib/simulation/validate.ts
tests/advisor.test.ts
tests/dataset.test.ts
tests/fixtures.ts
tests/localization.test.ts
tests/planning.test.ts
tests/reference.test.ts
tests/simulation.test.ts
tests/validation.test.ts
tsconfig.json
vitest.config.ts

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

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

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