diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..bd1be37 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,173 @@ + +# Vibe42 — учебная песочница для лендингов + +Workspace юзера `Ermek_aubakirov`. Это **учебная среда**, где обычные люди (не разработчики) пробуют сделать свой первый сайт. + +--- + +## 🎯 ТВОЯ РОЛЬ + +Ты — **гид и помощник**, а не слепой исполнитель. Цель сессии — чтобы юзер вышел с: +1. **рабочим лендингом**, опубликованным по адресу `https://pages.git.vibe42.kz/Ermek_aubakirov//`, +2. ощущением «это было легко» — без серверов, БД, токенов, конфигов. + +Юзер не разработчик. Ему важен **результат, который видно в браузере**, а не код. + +--- + +## 🗺 СЦЕНАРИЙ ПЕРВОГО ЗАХОДА (юзер только зашёл, ещё ничего нет) + +1. Поздоровайся коротко: «Привет! Тут за 10 минут собираем лендинг и публикуем его в интернете. О чём хочешь сделать?» +2. Если он не знает — предложи **4 конкретных идеи** (выбирай близкие к нему, не абстрактные): + - Промо хобби (фотография / музыка / спорт) + - Резюме / personal page с контактами + - Афиша мероприятия (концерт, день рождения, мастер-класс) + - Меню заведения / прайс услуг + - Лендинг продукта или будущего проекта (waitlist) +3. Уточни **2 короткие детали**: стиль (тёмный/светлый/яркий) и главную цель (рассказать / собрать заявку / показать работы). +4. Сразу делай `./new-project ` и собирай страницу. Не спрашивай разрешения на каждый шаг. + +--- + +## 💬 ЕСЛИ ЮЗЕР ОТВЕЧАЕТ РАСПЛЫВЧАТО + +Юзер говорит «сделай что-нибудь» / «ну хз» / «сюрприз» → **не делай ничего абстрактного**. + +Скажи: «Давай определимся, я задам 3 коротких вопроса: +1. Это для тебя лично, для проекта/бизнеса, или для события? +2. Главная цель — рассказать о чём-то / собрать заявку / показать портфолио? +3. Любимое настроение — строгое тёмное, лёгкое светлое, яркое цветное?» + +После ответов **сразу** предложи 2 конкретных варианта названия+структуры. Дай выбрать и иди делать. + +--- + +## 🚫 ЕСЛИ ЮЗЕР ХОЧЕТ СЛОЖНОЕ — ПЕРЕФОРМУЛИРУЙ В ЛЕНДИНГ + +| Запрос | Что делаем вместо | +|--------|-------------------| +| «магазин с корзиной» | лендинг с товарами + кнопка «купить» = ссылка на WhatsApp / Telegram | +| «соцсеть» | лендинг будущего проекта + waitlist-форма (Formspree / Getform) | +| «блог с админкой» | personal-page + ссылки на статьи в Telegram/Medium | +| «приложение для записи» | лендинг услуги + ссылка на Calendly / WhatsApp | +| «сайт с входом юзеров» | публичный лендинг без логина (нам логин не нужен) | +| «бот в Telegram» | лендинг с описанием бота + кнопка `t.me/...` | + +**Не говори «это невозможно».** Скажи: «У нас песочница только для статических сайтов. Давай сделаем лендинг, который покажет твою идею — а кнопки/формы свяжем с готовыми сервисами (WhatsApp, Telegram, Formspree)». Юзер счастлив, результат за 15 минут. + +--- + +## 📐 ШАБЛОНЫ СТРАНИЦ (выбирай под идею юзера) + +### A — Промо продукта/услуги +**Секции:** Hero (заголовок + подзаголовок + CTA-кнопка) → 3-4 преимущества (иконка emoji + текст) → социальное доказательство (отзыв или цифра) → CTA (кнопка/телефон/мессенджер). + +### B — Personal / резюме +**Секции:** Hero (фото-аватарка + имя + одна фраза «кто я») → О себе (1-2 абзаца) → 3-5 карточек проектов/опыта → Контакты (email, telegram, github как ссылки-кнопки). + +### C — Афиша мероприятия +**Секции:** Hero (название + дата + место крупно) → Программа (список с временем) → Локация (картинка-placeholder + адрес) → Регистрация (форма Formspree или контакт). + +### D — Меню / прайс +**Секции:** Hero (название + слоган) → Меню/прайс (категории с ценами) → Контакты (телефон, адрес, часы работы, карта-картинка). + +### E — Waitlist для будущего проекта +**Секции:** Hero (название проекта + одна фраза + email-форма) → 3 фичи «что будет» → FAQ (3 пункта) → CTA (та же email-форма). + +Все шаблоны — **одна страница, прокрутка вниз**. Никаких роутов, ничего динамического. + +--- + +## ⚡ РИТУАЛ ПОСЛЕ ПЕРВОГО ЗАПУСКА + +Как только готов первый рабочий вариант (даже грубый): + +1. **Сразу запушь:** + ```bash + git add -A + git commit -m "v1" + git push origin HEAD:pages + ``` +2. **ОБЯЗАТЕЛЬНО** дай юзеру ссылку **жирно**: + > 🎉 Готово! Твой лендинг здесь: **https://pages.git.vibe42.kz/Ermek_aubakirov//** +3. Скажи: «Открой в новой вкладке, посмотри. Что хочешь поменять?» +4. Дальше короткие итерации: правка → push → новый URL-показ. Каждые 2-3 правки — push. + +--- + +## ⚠️ ЖЕЛЕЗНЫЕ ПРАВИЛА (НЕ нарушать никогда) + +1. **Только статика — HTML + CSS + JS в браузере.** +2. **Никакого бэкенда.** Никаких Node/Express/FastAPI/Django/PHP/Go-серверов. Никаких БД. Никакого Redis. +3. **Никакой аутентификации / OAuth / JWT.** +4. **Никакого Docker, nginx, sudo, системных настроек.** +5. **Никаких тяжёлых сборщиков** (`npm install` дерево на 500МБ). Tailwind — только через CDN. +6. **НИКОГДА `git init` в workspace root (`/workspaces/Ermek_aubakirov`)** — это папка-контейнер юзера, не репозиторий. + +--- + +## ✅ ВСЕГДА работай через `./new-project` + +Если юзер сказал «сделай сайт NAME» / «создай проект NAME»: + +```bash +cd /workspaces/Ermek_aubakirov +./new-project NAME # создаёт repo в Gitea + клонит локально в ./NAME/ +cd NAME +# теперь создавай index.html / style.css / script.js внутри ./NAME +``` + +`./new-project` сам создаёт repo, клонит, и копирует туда `AGENTS.md` + `design.md`. + +--- + +## 🌐 Git и публикация + +**НЕТ GitHub.** Self-hosted git: **https://git.vibe42.kz** + +- Профиль юзера: https://git.vibe42.kz/Ermek_aubakirov +- Pages (живые лендинги): https://pages.git.vibe42.kz/Ermek_aubakirov// +- Креды уже в `/workspaces/Ermek_aubakirov/.git-credentials` — git push/clone работают без пароля +- **НЕ спрашивай юзера про GitHub URL / токен** — их не нужно + +### Опубликовать лендинг + +```bash +git add -A +git commit -m "site" +git push origin HEAD:pages +``` + +Ветка **`pages`** (Caddy её обслуживает; `gh-pages` тоже работает как fallback). Push → лендинг доступен мгновенно. + +--- + +## 🔧 Когда что-то идёт не так + +- **Pages 404** → запушь ветку `pages` снова: `git push origin HEAD:pages -f` +- **Не дёргай Gitea API типа `/repos/.../pages`, `/settings/pages`, `/deploy_keys`** — их нет +- **Не пытайся «настроить Pages через UI Gitea»** — Pages у нас работают только через push в ветку `pages` +- Запуталось — сделай новый чистый проект через `./new-project NAME-v2`, перенеси туда работающий index.html + +--- + +## ❌ Чего НЕ делать НИКОГДА + +- ❌ `git init` в workspace root +- ❌ `npm install` с прод-зависимостями (express/mongoose/pg/prisma/next/nuxt) +- ❌ Создавать `server.js` / `app.py` / `main.go` как backend +- ❌ Использовать `gh` CLI или GitHub API +- ❌ Вызывать Gitea Pages-API (его нет) +- ❌ Долгое отлаживание Pages — почти всегда решение «push HEAD:pages» +- ❌ Просить юзера ввести токен/URL/пароль — всё уже настроено +- ❌ Задавать юзеру 10 вопросов подряд (максимум 2-3 за раз) +- ❌ Показывать юзеру голый код больше 1 раза — ему важен результат, а не как написано +- ❌ Предлагать «давай сначала дизайн в Figma» — мы делаем сразу в HTML +- ❌ Говорить «это сложно» — переформулируй в простое +- ❌ Зависать в обсуждениях — сделай первый вариант грубо, потом итерируй + +--- + +## 🎨 design.md + +Рядом лежит `design.md` с готовой палитрой, типографикой и стартер-шаблоном `index.html`. **Начинай с него.** Не выдумывай новые цвета — модифицируй существующие. diff --git a/design.md b/design.md new file mode 100644 index 0000000..5c8e829 --- /dev/null +++ b/design.md @@ -0,0 +1,110 @@ + +# Design system — Vibe42 песочница + +Базовые цвета и типографика для лендингов. Можно отклоняться, но начинай с этого. + +## Палитра + +| Token | Hex | Использование | +|-------|-----|---------------| +| `--ink` | `#0F1218` | Тёмный фон / основной текст | +| `--cyan` | `#00E5FF` | Основной акцент (кнопки, лого) | +| `--cyan-50` | `#E8FCFF` | Светлая подложка для акцентов | +| `--white` | `#FFFFFF` | Основной фон | +| `--gray-500` | `#5B6573` | Вторичный текст | +| `--gray-100` | `#F2F4F7` | Сепараторы / тонкие фоны | + +## Типографика + +```css +font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif; +``` + +| Уровень | Размер | Вес | line-height | +|---------|--------|-----|-------------| +| h1 (hero) | 56px | 800 | 1.05 | +| h2 (section) | 36px | 700 | 1.15 | +| h3 | 22px | 700 | 1.3 | +| body | 17px | 400 | 1.6 | +| small | 14px | 400 | 1.5 | + +На мобиле — h1 уменьши до 36px, h2 до 28px. + +## Лейаут + +- max-width контента: **1140px** (контейнер с padding по бокам) +- секция: `padding: 80px 24px` (мобила: `48px 20px`) +- gap между блоками внутри секции: `24-32px` +- border-radius: `8px` (кнопки, карточки), `16px` (большие карточки) + +## Кнопки + +```css +.btn-primary { + background: var(--cyan); color: var(--ink); + padding: 14px 28px; border-radius: 8px; + font-weight: 700; text-decoration: none; + display: inline-block; +} +.btn-secondary { + background: transparent; color: var(--ink); + border: 2px solid var(--ink); + padding: 12px 26px; border-radius: 8px; +} +``` + +## Стартер `index.html` + +```html + + + + + +Мой проект + + + +
+
+

Заголовок проекта

+

Подзаголовок — пара предложений о чём это.

+ Начать +
+
+
+
+

Секция

+
Контент карточки.
+
Контент карточки.
+
+
+ + +``` + +## Чем НЕ пользоваться + +- Bootstrap, Material UI, Chakra, Ant Design — слишком тяжело и не нужно для лендинга +- Font Awesome — используй emoji (🚀 ⚡ ✨) или inline SVG +- jQuery — vanilla JS более чем достаточно + +## Чем МОЖНО (если очень надо) + +- **Tailwind через CDN**: `` — для прототипа OK +- **Lottie animations через CDN** +- **Placeholder картинки**: `https://picsum.photos/800/600`, `https://placehold.co/600x400` +- **Шрифты Google Fonts через ``** в head diff --git a/index.html b/index.html new file mode 100644 index 0000000..75a8dc8 --- /dev/null +++ b/index.html @@ -0,0 +1,126 @@ + + + + + +PoleMap — расстановка опор + + + + + + +
+ +
+
+

PoleMap

+

Расстановка опор связи на карте

+
+ +
+ +
+ + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    + +
    + + + + + +
    +

    Кликните на карту, чтобы поставить опору выбранного типа

    +
    + + +
    + + + +
    +
    +
    + + +
    +
    +
    +
    + +
    +
    + Опоры (0) + Нумерация по порядку установки +
    + + + + + + + + + + + + + + +
    ТипШиротаДолготаДист. до пред.
    Кликните на карту, чтобы добавить опору
    +
    +
    +
    + + + + + + diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..3a14a6a --- /dev/null +++ b/js/app.js @@ -0,0 +1,379 @@ +let map, drawnItems, poleLayer, connectionLayer; +let poles = []; +let poleCounter = 1; +let currentPoleType = "1"; + +const POLE_TYPES = { + "1": { name: "Промежуточная", color: "#2563eb", icon: "●" }, + "2": { name: "Угловая", color: "#dc2626", icon: "◆" }, + "3": { name: "С муфтой", color: "#ca8a04", icon: "◎" }, + "4": { name: "С ОРКсп", color: "#16a34a", icon: "◇" }, + "5": { name: "С муфтой и ОРКсп", color: "#7c3aed", icon: "★" }, +}; + +function initApp() { + initMap(); + initSelectors(); + initPoleControls(); + updateTable(); +} + +function initMap() { + map = L.map("map", { zoomControl: true }).setView([48.0, 68.0], 6); + L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { + attribution: "© OpenStreetMap", + maxZoom: 19, + }).addTo(map); + + drawnItems = L.featureGroup().addTo(map); + poleLayer = L.featureGroup().addTo(map); + connectionLayer = L.featureGroup().addTo(map); + + map.on("click", function (e) { + addPole(e.latlng.lat, e.latlng.lng); + }); +} + +function initSelectors() { + const oblastSel = document.getElementById("oblast"); + const rayonSel = document.getElementById("rayon"); + const villageSel = document.getElementById("village"); + const searchInput = document.getElementById("searchInput"); + + KZ_DATA.forEach((o) => { + const opt = document.createElement("option"); + opt.value = o.oblast; + opt.textContent = o.oblast; + oblastSel.appendChild(opt); + }); + + function updateRayons() { + rayonSel.innerHTML = ''; + villageSel.innerHTML = ''; + const oblast = KZ_DATA.find((o) => o.oblast === oblastSel.value); + if (!oblast) return; + oblast.rayons.forEach((r) => { + const opt = document.createElement("option"); + opt.value = r.rayon; + opt.textContent = r.rayon; + rayonSel.appendChild(opt); + }); + updateVillages(); + } + + function updateVillages() { + villageSel.innerHTML = ''; + const oblast = KZ_DATA.find((o) => o.oblast === oblastSel.value); + if (!oblast) return; + const rayon = oblast.rayons.find((r) => r.rayon === rayonSel.value); + if (!rayon) return; + rayon.villages.forEach((v) => { + const opt = document.createElement("option"); + opt.value = v; + opt.textContent = v; + villageSel.appendChild(opt); + }); + } + + oblastSel.addEventListener("change", updateRayons); + rayonSel.addEventListener("change", updateVillages); + + villageSel.addEventListener("change", function () { + const name = this.value; + if (!name) return; + const oblast = KZ_DATA.find((o) => o.oblast === oblastSel.value); + if (!oblast) return; + map.setView(oblast.center, 10); + L.popup() + .setLatLng(oblast.center) + .setContent(`${name}
    ${oblast.oblast}, ${rayonSel.value}`) + .openOn(map); + }); + + searchInput.addEventListener("input", function () { + const q = this.value.toLowerCase().trim(); + if (q.length < 2) return; + const results = []; + KZ_DATA.forEach((o) => { + o.rayons.forEach((r) => { + r.villages.forEach((v) => { + if (v.toLowerCase().includes(q)) { + results.push({ village: v, rayon: r.rayon, oblast: o.oblast, center: o.center }); + } + }); + }); + }); + const list = document.getElementById("searchResults"); + list.innerHTML = ""; + if (results.length === 0 || results.length > 50) { + if (results.length > 50) list.innerHTML = "
  • Слишком много результатов, уточните
  • "; + return; + } + results.slice(0, 20).forEach((r) => { + const li = document.createElement("li"); + li.className = "px-3 py-2 cursor-pointer hover:bg-cyan-50"; + li.textContent = `${r.village} — ${r.rayon}, ${r.oblast}`; + li.addEventListener("click", () => { + oblastSel.value = r.oblast; + updateRayons(); + rayonSel.value = r.rayon; + updateVillages(); + villageSel.value = r.village; + map.setView(r.center, 12); + L.popup() + .setLatLng(r.center) + .setContent(`${r.village}
    ${r.oblast}, ${r.rayon}`) + .openOn(map); + list.innerHTML = ""; + searchInput.value = r.village; + }); + list.appendChild(li); + }); + }); + + document.addEventListener("click", function (e) { + if (!e.target.closest("#searchResults") && !e.target.closest("#searchInput")) { + document.getElementById("searchResults").innerHTML = ""; + } + }); +} + +function initPoleControls() { + document.querySelectorAll(".pole-type-btn").forEach((btn) => { + btn.addEventListener("click", function () { + document.querySelectorAll(".pole-type-btn").forEach((b) => b.classList.remove("active")); + this.classList.add("active"); + currentPoleType = this.dataset.type; + }); + }); + document.querySelector('[data-type="1"]').classList.add("active"); +} + +function addPole(lat, lng) { + const type = POLE_TYPES[currentPoleType]; + const id = poleCounter++; + const pole = { id, lat, lng, type: currentPoleType, label: `Опора ${id}` }; + poles.push(pole); + renderPole(pole); + updateTable(); + updateConnections(); +} + +function renderPole(pole) { + const type = POLE_TYPES[pole.type]; + const icon = L.divIcon({ + className: "pole-marker", + html: `
    ${pole.id}
    `, + iconSize: [28, 28], + iconAnchor: [14, 14], + }); + + const marker = L.marker([pole.lat, pole.lng], { icon }).addTo(poleLayer); + marker.bindPopup(` + ${pole.label}
    + Тип: ${type.name}
    + Координаты: ${pole.lat.toFixed(6)}, ${pole.lng.toFixed(6)} +
    + `); + pole._marker = marker; +} + +function removePole(id) { + const idx = poles.findIndex((p) => p.id === id); + if (idx === -1) return; + const pole = poles[idx]; + if (pole._marker) poleLayer.removeLayer(pole._marker); + poles.splice(idx, 1); + poles.forEach((p, i) => { + p.id = i + 1; + p.label = `Опора ${i + 1}`; + }); + poleCounter = poles.length + 1; + poleLayer.clearLayers(); + poles.forEach((p) => renderPole(p)); + updateTable(); + updateConnections(); +} + +function updateConnections() { + connectionLayer.clearLayers(); + if (poles.length < 2) return; + + const sorted = [...poles].sort((a, b) => a.id - b.id); + for (let i = 0; i < sorted.length - 1; i++) { + const a = sorted[i]; + const b = sorted[i + 1]; + const polyline = L.polyline( + [ + [a.lat, a.lng], + [b.lat, b.lng], + ], + { color: "#64748b", weight: 2, dashArray: "6,4", opacity: 0.7 } + ).addTo(connectionLayer); + + const midLat = (a.lat + b.lat) / 2; + const midLng = (a.lng + b.lng) / 2; + const dist = calcDistance(a.lat, a.lng, b.lat, b.lng); + L.marker([midLat, midLng], { + icon: L.divIcon({ + className: "dist-label", + html: `
    ${dist.toFixed(1)} м
    `, + iconSize: [0, 0], + iconAnchor: [0, 0], + }), + }).addTo(connectionLayer); + } +} + +function updateTable() { + document.getElementById("poleCount").textContent = poles.length; + const tbody = document.querySelector("#poleTable tbody"); + tbody.innerHTML = ""; + if (poles.length === 0) { + tbody.innerHTML = 'Нет опор. Кликните на карту, чтобы добавить.'; + return; + } + + const sorted = [...poles].sort((a, b) => a.id - b.id); + sorted.forEach((p, i) => { + const type = POLE_TYPES[p.type]; + const prevDist = + i > 0 + ? calcDistance(sorted[i - 1].lat, sorted[i - 1].lng, p.lat, p.lng).toFixed(1) + : "—"; + const tr = document.createElement("tr"); + tr.className = "border-b border-gray-200 hover:bg-gray-50"; + tr.innerHTML = ` + ${p.id} + ${type.name} + ${p.lat.toFixed(6)} + ${p.lng.toFixed(6)} + ${prevDist} + + + + `; + tbody.appendChild(tr); + }); +} + +function calcDistance(lat1, lon1, lat2, lon2) { + const R = 6371000; + const dLat = ((lat2 - lat1) * Math.PI) / 180; + const dLon = ((lon2 - lon1) * Math.PI) / 180; + const a = + Math.sin(dLat / 2) ** 2 + + Math.cos((lat1 * Math.PI) / 180) * + Math.cos((lat2 * Math.PI) / 180) * + Math.sin(dLon / 2) ** 2; + return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); +} + +function clearAll() { + if (poles.length === 0) return; + if (!confirm("Удалить все опоры?")) return; + poleLayer.clearLayers(); + connectionLayer.clearLayers(); + poles = []; + poleCounter = 1; + updateTable(); +} + +function exportSVG() { + if (poles.length === 0) return alert("Нет опор для экспорта"); + + const padding = 50; + const lats = poles.map((p) => p.lat); + const lngs = poles.map((p) => p.lng); + const minLat = Math.min(...lats); + const maxLat = Math.max(...lats); + const minLng = Math.min(...lngs); + const maxLng = Math.max(...lngs); + const latRange = maxLat - minLat || 0.001; + const lngRange = maxLng - minLng || 0.001; + + const scale = 500 / Math.max(latRange, lngRange); + const toX = (lng) => padding + ((lng - minLng) / lngRange) * 500; + const toY = (lat) => padding + ((maxLat - lat) / latRange) * 500; + const w = 500 + padding * 2; + const h = 500 + padding * 2; + + let svg = ` + + +Схема расположения опор`; + + const sorted = [...poles].sort((a, b) => a.id - b.id); + + // connections + for (let i = 0; i < sorted.length - 1; i++) { + const a = sorted[i], + b = sorted[i + 1]; + const dist = calcDistance(a.lat, a.lng, b.lat, b.lng).toFixed(1); + const mx = (toX(a.lng) + toX(b.lng)) / 2; + const my = (toY(a.lat) + toY(b.lat)) / 2; + svg += ``; + svg += `${dist} м`; + } + + // poles + sorted.forEach((p) => { + const type = POLE_TYPES[p.type]; + const cx = toX(p.lng); + const cy = toY(p.lat); + svg += ``; + svg += `${p.id}`; + svg += `${p.label} (${type.name})`; + }); + + // Legend + const legendY = h - 40; + svg += ``; + let lx = padding; + Object.entries(POLE_TYPES).forEach(([k, t]) => { + svg += ``; + svg += `${t.name}`; + lx += 140; + }); + + svg += ``; + + downloadFile(svg, "opory.svg", "image/svg+xml"); +} + +function exportVSD() { + alert( + "VSD (Visio) — бинарный формат. SVG можно открыть в Visio.\n\n" + + "Экспортируйте в SVG, затем откройте в Visio: Файл → Открыть → выберите .svg\n" + + "Или перетащите SVG-файл в окно Visio." + ); +} + +function downloadFile(content, filename, mime) { + const blob = new Blob([content], { type: mime }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = filename; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); +} + +document.addEventListener("DOMContentLoaded", initApp); diff --git a/js/kz-data.js b/js/kz-data.js new file mode 100644 index 0000000..3672d8d --- /dev/null +++ b/js/kz-data.js @@ -0,0 +1,294 @@ +const KZ_DATA = [ + { + oblast: "Акмолинская", center: [52.25, 69.35], + rayons: [ + { rayon: "Целиноградский", villages: ["Косшы", "Кабанбай батыра", "Тайтобе", "Акмол"] }, + { rayon: "Аккольский", villages: ["Акколь", "Енбек", "Жалгызкарагай"] }, + { rayon: "Аршалынский", villages: ["Аршалы", "Ижевское", "Булаксай"] }, + { rayon: "Астраханский", villages: ["Астраханка", "Жалтыр", "Новочеркасское"] }, + { rayon: "Атбасарский", villages: ["Атбасар", "Сочинское", "Борисовка"] }, + { rayon: "Буландынский", villages: ["Макинск", "Пушкино", "Айнаколь"] }, + { rayon: "Бурабайский", villages: ["Щучинск", "Бурабай", "Зеленый Бор"] }, + { rayon: "Егиндыкольский", villages: ["Егиндыколь", "Абай", "Коркыт"] }, + { rayon: "Ерейментауский", villages: ["Ерейментау", "Ынтымак", "Торгай"] }, + { rayon: "Есильский", villages: ["Есиль", "Каратал", "Бузулук"] }, + { rayon: "Жаксынский", villages: ["Жаксы", "Беловодское", "Кайракты"] }, + { rayon: "Жаркаинский", villages: ["Державинск", "Пригородное", "Тасоткель"] }, + { rayon: "Зерендинский", villages: ["Зеренда", "Викторовка", "Кызылагаш"] }, + { rayon: "Коргалжынский", villages: ["Коргалжын", "Талдыколь", "Майшукыр"] }, + { rayon: "Сандыктауский", villages: ["Балкашино", "Максимовка", "Сандыктау"] }, + { rayon: "Биржан сал", villages: ["Степняк", "Кенесары", "Андыкожа батыра"] }, + ] + }, + { + oblast: "Актюбинская", center: [50.28, 57.21], + rayons: [ + { rayon: "Актобе", villages: ["Актобе", "Киргизское", "Курайли"] }, + { rayon: "Алгинский", villages: ["Алга", "Бескоспа", "Тамды"] }, + { rayon: "Айтекебийский", villages: ["Темирбека Жургенова", "Аккудык", "Торткудык"] }, + { rayon: "Байганинский", villages: ["Карауылкельды", "Кемерши", "Кызылбулак"] }, + { rayon: "Иргизский", villages: ["Иргиз", "Аманколь", "Каракудык"] }, + { rayon: "Каргалинский", villages: ["Богетсай", "Алимбет", "Косестек"] }, + { rayon: "Мартукский", villages: ["Мартук", "Каратаусай", "Кызылжар"] }, + { rayon: "Мугалжарский", villages: ["Кандыагаш", "Енбек", "Жагабулак"] }, + { rayon: "Темирский", villages: ["Шубаркудык", "Шубарши", "Кенкияк"] }, + { rayon: "Уилский", villages: ["Уил", "Карасу", "Сандыколь"] }, + { rayon: "Хобдинский", villages: ["Кобда", "Кызылжар", "Байтарак"] }, + { rayon: "Хромтауский", villages: ["Хромтау", "Абай", "Копта"] }, + { rayon: "Шалкарский", villages: ["Шалкар", "Биршогыр", "Тогыз"] }, + ] + }, + { + oblast: "Алматинская", center: [44.85, 76.95], + rayons: [ + { rayon: "Конаев", villages: ["Конаев", "Шенгельды", "Коккайнар"] }, + { rayon: "Балхашский", villages: ["Баканас", "Акжиде", "Караой"] }, + { rayon: "Енбекшиказахский", villages: ["Есик", "Тургень", "Маловодное"] }, + { rayon: "Жамбылский", villages: ["Узынагаш", "Каргалы", "Жамбыл"] }, + { rayon: "Илийский", villages: ["Отеген батыра", "Боралдай", "Ащыбулак"] }, + { rayon: "Карасайский", villages: ["Каскелен", "Шамалган", "Айтей"] }, + { rayon: "Кегенский", villages: ["Кеген", "Талды", "Жанатай"] }, + { rayon: "Райымбекский", villages: ["Нарынкол", "Карасаз", "Жанасу"] }, + { rayon: "Талгарский", villages: ["Талгар", "Белбулак", "Достык"] }, + { rayon: "Уйгурский", villages: ["Чунджа", "Кетмень", "Ават"] }, + ] + }, + { + oblast: "Атырауская", center: [47.1, 51.88], + rayons: [ + { rayon: "Атырау", villages: ["Атырау", "Томарлы", "Аксай"] }, + { rayon: "Индерский", villages: ["Индербор", "Коктогай", "Орлик"] }, + { rayon: "Исатайский", villages: ["Исатай", "Зинеден", "Тущыкудык"] }, + { rayon: "Кзылкогинский", villages: ["Кызылкога", "Жамбыл", "Коныстану"] }, + { rayon: "Курмангазинский", villages: ["Курмангазы", "Азгир", "Балкудук"] }, + { rayon: "Макатский", villages: ["Макат", "Байчунас", "Доссор"] }, + { rayon: "Махамбетский", villages: ["Махамбет", "Бейбарыс", "Акжайык"] }, + ] + }, + { + oblast: "Западно-Казахстанская", center: [51.23, 51.37], + rayons: [ + { rayon: "Уральск", villages: ["Уральск", "Круглоозерное", "Деркул"] }, + { rayon: "Акжаикский", villages: ["Тайпак", "Алгабас", "Базартобе"] }, + { rayon: "Бокейординский", villages: ["Сайхин", "Бисен", "Каратобе"] }, + { rayon: "Бурлинский", villages: ["Аксай", "Пугачево", "Кентубек"] }, + { rayon: "Жангалинский", villages: ["Жангала", "Кызылоба", "Копжасар"] }, + { rayon: "Жанибекский", villages: ["Жанибек", "Камысты", "Куйгенколь"] }, + { rayon: "Казталовский", villages: ["Казталовка", "Караоба", "Болашак"] }, + { rayon: "Каратобинский", villages: ["Каратобе", "Жусандой", "Акжол"] }, + { rayon: "Сырымский", villages: ["Жымпиты", "Аралтобе", "Кособа"] }, + { rayon: "Таскалинский", villages: ["Таскала", "Достык", "Каменка"] }, + { rayon: "Теректинский", villages: ["Федоровка", "Тонкерис", "Акжайык"] }, + { rayon: "Чингирлауский", villages: ["Чингирлау", "Шынгырлау", "Аксу"] }, + ] + }, + { + oblast: "Жамбылская", center: [42.82, 71.43], + rayons: [ + { rayon: "Тараз", villages: ["Тараз", "Карасу", "Кулан"] }, + { rayon: "Байзакский", villages: ["Сарыкемер", "Коптерек", "Бурыл"] }, + { rayon: "Жамбылский", villages: ["Аса", "Каратобе", "Айша-Биби"] }, + { rayon: "Жуалынский", villages: ["Курдай", "Актобе", "Кокбастау"] }, + { rayon: "Кордайский", villages: ["Кордай", "Масанчи", "Карасу"] }, + { rayon: "Меркенский", villages: ["Мерке", "Тау", "Акарал"] }, + { rayon: "Мойынкумский", villages: ["Мойынкум", "Бидайколь", "Байтал"] }, + { rayon: "Сарысуский", villages: ["Жанатас", "Сарысу", "Байкадам"] }, + { rayon: "Таласский", villages: ["Акколь", "Кенен", "Сегизсай"] }, + { rayon: "Турара Рыскулова", villages: ["Кулан", "Каменка", "Абай"] }, + { rayon: "Шуский", villages: ["Толе би", "Шу", "Акшу"] }, + ] + }, + { + oblast: "Жетысуская", center: [45.0, 78.38], + rayons: [ + { rayon: "Талдыкорган", villages: ["Талдыкорган", "Еркин", "Каратал"] }, + { rayon: "Аксуский", villages: ["Жансугуров", "Аксу", "Мукыр"] }, + { rayon: "Алакольский", villages: ["Кабанбай", "Достык", "Кокжар"] }, + { rayon: "Ескельдинский", villages: ["Карабулак", "Талдыбулак", "Кайнарлы"] }, + { rayon: "Каратальский", villages: ["Уштобе", "Каратал", "Айдарлы"] }, + { rayon: "Кербулакский", villages: ["Сарыозек", "Сарыбулак", "Кулык"] }, + { rayon: "Коксуский", villages: ["Балпык би", "Коксу", "Майлыбас"] }, + { rayon: "Панфиловский", villages: ["Жаркент", "Аухатты", "Коктал"] }, + { rayon: "Саркандский", villages: ["Сарканд", "Амангельды", "Караой"] }, + ] + }, + { + oblast: "Карагандинская", center: [49.8, 73.09], + rayons: [ + { rayon: "Караганда", villages: ["Караганда", "Сортировка", "Кокпекты"] }, + { rayon: "Абайский", villages: ["Абай", "Топар", "Карабас"] }, + { rayon: "Актогайский", villages: ["Актогай", "Нуркен", "Сарышаган"] }, + { rayon: "Бухар-Жырауский", villages: ["Ботакара", "Габидена Мустафина", "Самарканд"] }, + { rayon: "Каркаралинский", villages: ["Каркаралинск", "Егиндыбулак", "Коянды"] }, + { rayon: "Нуринский", villages: ["Баршино", "Нура", "Кызылжар"] }, + { rayon: "Осакаровский", villages: ["Осакаровка", "Молодежный", "Карагайлы"] }, + { rayon: "Шетский", villages: ["Коктенколь", "Аксу-Аюлы", "Мойынты"] }, + ] + }, + { + oblast: "Костанайская", center: [53.22, 63.62], + rayons: [ + { rayon: "Костанай", villages: ["Костанай", "Затобольск", "Ульяновское"] }, + { rayon: "Алтынсаринский", villages: ["Убаган", "Докучаевка", "Кутиховка"] }, + { rayon: "Амангельдинский", villages: ["Амангельды", "Карасу", "Бидайык"] }, + { rayon: "Аулиекольский", villages: ["Аулиеколь", "Диевка", "Сулыколь"] }, + { rayon: "Беимбета Майлина", villages: ["Науырзым", "Тарановское", "Баталы"] }, + { rayon: "Денисовский", villages: ["Денисовка", "Архангельское", "Глебовка"] }, + { rayon: "Жангельдинский", villages: ["Торгай", "Калмакколь", "Айшырык"] }, + { rayon: "Житикаринский", villages: ["Житикара", "Кировка", "Степной"] }, + { rayon: "Камыстинский", villages: ["Камысты", "Карабатыр", "Аралколь"] }, + { rayon: "Карабалыкский", villages: ["Карабалык", "Победа", "Славянка"] }, + { rayon: "Карасуский", villages: ["Карасу", "Октябрьское", "Койбагар"] }, + { rayon: "Костанайский", villages: ["Тобыл", "Москалевка", "Александровка"] }, + { rayon: "Мендыкаринский", villages: ["Боровской", "Каменка", "Первомайское"] }, + { rayon: "Сарыкольский", villages: ["Сарыколь", "Большие Дубравы", "Лесной"] }, + { rayon: "Узункольский", villages: ["Узунколь", "Ряжское", "Пресногорьковка"] }, + { rayon: "Федоровский", villages: ["Федоровка", "Веселоярка", "Пешковка"] }, + ] + }, + { + oblast: "Кызылординская", center: [44.85, 65.52], + rayons: [ + { rayon: "Кызылорда", villages: ["Кызылорда", "Кызылжарма", "Талсуат"] }, + { rayon: "Аральский", villages: ["Аральск", "Жанаконыс", "Аманоткель"] }, + { rayon: "Жалагашский", villages: ["Жалагаш", "Торткудык", "Енбек"] }, + { rayon: "Казалинский", villages: ["Айтеке би", "Уркендеу", "Кызылкум"] }, + { rayon: "Кармакшинский", villages: ["Жосалы", "Далабай", "Торетам"] }, + { rayon: "Сырдарьинский", villages: ["Теренозек", "Когалыколь", "Кызылкак"] }, + { rayon: "Чиилийский", villages: ["Шиели", "Тартогай", "Балаби"] }, + { rayon: "Яныкурганский", villages: ["Жанибек", "Когалы", "Куйган"] }, + ] + }, + { + oblast: "Мангистауская", center: [43.65, 51.15], + rayons: [ + { rayon: "Актау", villages: ["Актау", "Умирзак", "Сауга"] }, + { rayon: "Бейнеуский", villages: ["Бейнеу", "Турыш", "Акжигит"] }, + { rayon: "Каракиянский", villages: ["Курык", "Баутино", "Каракия"] }, + { rayon: "Мангистауский", villages: ["Жетыбай", "Шетпе", "Аксу"] }, + { rayon: "Мунайлинский", villages: ["Мангистау", "Тенге", "Баянды"] }, + { rayon: "Тупкараганский", villages: ["Форт-Шевченко", "Таучик", "Баутино"] }, + ] + }, + { + oblast: "Павлодарская", center: [52.28, 76.95], + rayons: [ + { rayon: "Павлодар", villages: ["Павлодар", "Кенжеколь", "Мойылды"] }, + { rayon: "Аккулинский", villages: ["Акку", "Амангельды", "Кызылжар"] }, + { rayon: "Актогайский", villages: ["Актогай", "Харьковка", "Куттерген"] }, + { rayon: "Баянаульский", villages: ["Баянаул", "Каракамыс", "Бирлик"] }, + { rayon: "Железинский", villages: ["Железинка", "Енбекши", "Башмачное"] }, + { rayon: "Иртышский", villages: ["Иртышск", "Голубовка", "Панфилово"] }, + { rayon: "Майский", villages: ["Коктобе", "Майкарагай", "Кентубек"] }, + { rayon: "Павлодарский", villages: ["Ленинский", "Черноярка", "Красноармейка"] }, + { rayon: "Теренкольский", villages: ["Теренколь", "Береговое", "Тогузак"] }, + { rayon: "Успенский", villages: ["Успенка", "Богодаровка", "Чернорецк"] }, + { rayon: "Щербактинский", villages: ["Щербакты", "Галкино", "Алексеевка"] }, + ] + }, + { + oblast: "Северо-Казахстанская", center: [54.87, 69.14], + rayons: [ + { rayon: "Петропавловск", villages: ["Петропавловск", "Новопавловка", "Бишкуль"] }, + { rayon: "Айыртауский", villages: ["Саумалколь", "Имантау", "Лобаново"] }, + { rayon: "Акжарский", villages: ["Талшик", "Ленинградское", "Ульгули"] }, + { rayon: "Аккайынский", villages: ["Смирново", "Киялы", "Трудовое"] }, + { rayon: "Есильский", villages: ["Явленка", "Покровка", "Чкалово"] }, + { rayon: "Жамбылский", villages: ["Пресновка", "Май-Балык", "Вознесенка"] }, + { rayon: "Кызылжарский", villages: ["Бесколь", "Коньково", "Прибрежное"] }, + { rayon: "Магжана Жумабаева", villages: ["Булаево", "Молодогвардейское", "Возвышенка"] }, + { rayon: "Мамлютский", villages: ["Мамлютка", "Дубровное", "Покровка"] }, + { rayon: "Тайыншинский", villages: ["Тайынша", "Чкалово", "Кирово"] }, + { rayon: "Тимирязевский", villages: ["Тимирязево", "Есиль", "Комсомольское"] }, + { rayon: "Уалихановский", villages: ["Кишкенеколь", "Акбулак", "Карасу"] }, + { rayon: "Шал акына", villages: ["Сергеевка", "Новопокровка", "Пригородное"] }, + ] + }, + { + oblast: "Туркестанская", center: [42.33, 69.59], + rayons: [ + { rayon: "Туркестан", villages: ["Туркестан", "Акжар", "Коксу"] }, + { rayon: "Темирлановка", villages: ["Темирлановка", "Каскелен", "Керейт"] }, + { rayon: "Байдибекский", villages: ["Шаян", "Боралдай", "Коктерек"] }, + { rayon: "Жетысайский", villages: ["Жетысай", "Асыката", "Ынтымак"] }, + { rayon: "Казыгуртский", villages: ["Казыгурт", "Турбат", "Шарбулак"] }, + { rayon: "Келесский", villages: ["Абай", "Кошкарата", "Каратобе"] }, + { rayon: "Мактааральский", villages: ["Атакент", "Ильичевка", "Макталы"] }, + { rayon: "Ордабасынский", villages: ["Темирлановка", "Бугунь", "Караспан"] }, + { rayon: "Отырарский", villages: ["Шаульдер", "Караконыр", "Коктобе"] }, + { rayon: "Сайрамский", villages: ["Аксукент", "Сайрам", "Манкент"] }, + { rayon: "Сарыагашский", villages: ["Сарыагаш", "Жылга", "Дарбаза"] }, + { rayon: "Созакский", villages: ["Шолаккорган", "Созак", "Каракур"] }, + { rayon: "Толебийский", villages: ["Толе би", "Каратау", "Акжар"] }, + { rayon: "Тюлькубасский", villages: ["Тюлькубас", "Майлыкент", "Алатау"] }, + { rayon: "Шардаринский", villages: ["Шардара", "Коксу", "Акшенгельды"] }, + ] + }, + { + oblast: "Улытауская", center: [47.78, 67.7], + rayons: [ + { rayon: "Жезказган", villages: ["Жезказган", "Кенгир", "Сарыкенгир"] }, + { rayon: "Жанааркинский", villages: ["Жанаарка", "Актубек", "Байдалы"] }, + { rayon: "Улытауский", villages: ["Улытау", "Аксу-Аюлы", "Жезды"] }, + { rayon: "Сатпаев", villages: ["Сатпаев", "Карсакпай", "Кенгирское"] }, + ] + }, + { + oblast: "Восточно-Казахстанская", center: [49.98, 82.62], + rayons: [ + { rayon: "Усть-Каменогорск", villages: ["Усть-Каменогорск", "Ахмирово", "Меновное"] }, + { rayon: "Алтайский", villages: ["Перевальное", "Снегирево", "Куйбышево"] }, + { rayon: "Глубоковский", villages: ["Глубокое", "Быструха", "Малоубинка"] }, + { rayon: "Зайсанский", villages: ["Зайсан", "Карабулак", "Акарал"] }, + { rayon: "Катон-Карагайский", villages: ["Катон-Карагай", "Улкен Нарын", "Коробиха"] }, + { rayon: "Куршимский", villages: ["Куршим", "Кызылжар", "Маралды"] }, + { rayon: "Самарский", villages: ["Самарское", "Каратюбе", "Кокжыра"] }, + { rayon: "Тарбагатайский", villages: ["Акжар", "Кокжыра", "Толеугали"] }, + { rayon: "Уланский", villages: ["Касыма Кайсенова", "Мамай батыра", "Кабанбай"] }, + { rayon: "Шемонаихинский", villages: ["Шемонаиха", "Усть-Таловка", "Первомайский"] }, + ] + }, + { + oblast: "Абайская", center: [50.39, 80.25], + rayons: [ + { rayon: "Семей", villages: ["Семей", "Карауыл", "Знаменка"] }, + { rayon: "Абайский", villages: ["Карауыл", "Кокбай", "Кунанбай"] }, + { rayon: "Аягозский", villages: ["Аягоз", "Тарлаулы", "Мадениет"] }, + { rayon: "Бескарагайский", villages: ["Бескарагай", "Долонь", "Канонерка"] }, + { rayon: "Бородулихинский", villages: ["Бородулиха", "Новопокровка", "Новодворовка"] }, + { rayon: "Жанасемейский", villages: ["Кайнар", "Коркыт", "Каменка"] }, + { rayon: "Кокпектинский", villages: ["Кокпекты", "Тасшокы", "Кокжайык"] }, + { rayon: "Урджарский", villages: ["Урджар", "Каракол", "Маканчи"] }, + ] + }, + { + oblast: "Астана", center: [51.13, 71.43], + rayons: [ + { rayon: "Алматинский", villages: ["Астана", "Аксу", "Интернациональный"] }, + { rayon: "Байконурский", villages: ["Астана", "Куйгенжар", "Каражар"] }, + { rayon: "Есильский", villages: ["Астана", "Зеленый Квартал", "Жагалау"] }, + { rayon: "Сарыаркинский", villages: ["Астана", "Коктал", "Пригородное"] }, + ] + }, + { + oblast: "Алматы", center: [43.24, 76.89], + rayons: [ + { rayon: "Алмалы", villages: ["Алматы", "Каменка", "Гульдала"] }, + { rayon: "Ауэзов", villages: ["Алматы", "Калкаман", "Теректы"] }, + { rayon: "Бостандык", villages: ["Алматы", "Нур-Алатау", "Карагайлы"] }, + { rayon: "Жетысу", villages: ["Алматы", "Айнабулак", "Коктобе"] }, + { rayon: "Медеу", villages: ["Алматы", "Кумбель", "Бутаковка"] }, + { rayon: "Наурызбай", villages: ["Алматы", "Таугуль", "Калкаман"] }, + { rayon: "Турксиб", villages: ["Алматы", "Жулдыз", "Отеген"] }, + ] + }, + { + oblast: "Шымкент", center: [42.32, 69.60], + rayons: [ + { rayon: "Абай", villages: ["Шымкент", "Сайрам", "Каратобе"] }, + { rayon: "Енбекши", villages: ["Шымкент", "Туран", "Жанаталап"] }, + { rayon: "Каратау", villages: ["Шымкент", "Кызылжар", "Тайбурыл"] }, + { rayon: "Аль-Фараби", villages: ["Шымкент", "Акжайык", "Казына"] }, + ] + } +];