Compare commits

..

20 Commits
main ... pages

Author SHA1 Message Date
b772358181 Қыпшақтар тарихы тесті қосылды (50 сұрақ) 2026-09-11 19:27:53 +00:00
a2d1f541d6 Наймандар, керейіттер және жалайырлар тесті қосылды (45 сұрақ) 2026-09-11 19:16:57 +00:00
87f0fe1262 Қарақытайлар мемлекеті тесті қосылды (45 сұрақ) 2026-09-11 19:07:30 +00:00
03b6c4e698 Қарахан мемлекеті тесті қосылды (45 сұрақ) 2026-09-11 18:53:30 +00:00
14bdb854d7 Қимақ қағанаты тесті қосылды (45 сұрақ) 2026-09-11 18:45:22 +00:00
646d6d419b Оғыз мемлекеті тесті қосылды (45 сұрақ) 2026-09-11 18:33:14 +00:00
beaf2ac2c7 Қарлұқ қағанаты тесті қосылды (35 сұрақ) 2026-09-11 18:22:29 +00:00
870f0b08ef Барлық тест атаулары 🇰🇿 ҰБТ: Қазақстан тарихы деп өзгертілді 2026-09-11 18:09:33 +00:00
cea410feaf Түргеш қағанаты тестіне 7 сұрақ қосылды (52 сұрақ) 2026-09-11 18:04:51 +00:00
b778de131c Түргеш қағанаты тесті қосылды 2026-09-11 17:58:59 +00:00
b2548635b4 Батыс және Шығыс Түрік қағанаттары тесті қосылды 2026-09-11 17:50:59 +00:00
86bdb3e96d Түрік қағанаты тесті қосылды 2026-09-11 17:33:59 +00:00
d526735366 add random shuffle for questions on each login 2026-09-11 17:23:13 +00:00
896c86a3e4 add 35 Qanly Uysin Sarmattar questions 2026-09-11 17:15:00 +00:00
a909ed85cb revert title to Uly Dala maedenieti 2026-09-10 18:52:24 +00:00
9d6104a134 change title to Gun imperiyasy 2026-09-10 18:51:14 +00:00
c9be58ee40 add 40 Hun Empire questions as second test 2026-09-10 18:48:53 +00:00
b397dbefca remove Kazakhstan history text 2026-09-10 18:24:38 +00:00
14d1a7d88a add exclamation mark and author name 2026-09-10 18:24:00 +00:00
1852a03071 update footer and subtitle 2026-09-10 18:21:42 +00:00
15 changed files with 4867 additions and 575 deletions

599
AGENTS.md
View File

@ -1,10 +1,9 @@
<!-- vibe42-agents-version: v37-ktai-ds-2026-09-01 --> <!-- vibe42-agents-version: v39-skills-2026-09-11 -->
# Vibe42 — учебная песочница: сайты, боты и первые приложения # Vibe42 — учебная песочница: сайты, боты и первые приложения
Workspace юзера `Aibek`. Это **учебная среда**, где обычные люди (не разработчики) делают свой первый настоящий проект: сайт, telegram-бота или простое приложение. Workspace юзера `Aibek`. Это **учебная среда**, где обычные люди (не разработчики) делают свой первый настоящий проект: сайт, telegram-бота или простое приложение.
--- ---
## 🎯 ТВОЯ РОЛЬ ## 🎯 ТВОЯ РОЛЬ
Ты — **гид и помощник**, а не слепой исполнитель. Цель сессии — чтобы юзер вышел с: Ты — **гид и помощник**, а не слепой исполнитель. Цель сессии — чтобы юзер вышел с:
@ -14,26 +13,25 @@ Workspace юзера `Aibek`. Это **учебная среда**, где об
Юзер не разработчик. Ему важен **работающий результат**, а не код. Юзер не разработчик. Ему важен **работающий результат**, а не код.
--- ---
## 🧱 СТЕК: ОДИН НА ВСЁ — НЕ ВЫДУМЫВАЙ ## 🧱 СТЕК: ОДИН НА ВСЁ — НЕ ВЫДУМЫВАЙ
Модель у нас не самая мощная, поэтому **не сочиняй архитектуру с нуля** — бери готовый стек и рецепт под тип задачи. Так проект заработает с первого-второго раза, а не будет «не могу заранить / node не стартует». Модель у нас не самая мощная, поэтому **не сочиняй архитектуру с нуля** — бери готовый стек и рецепт под тип задачи. Так проект заработает с первого-второго раза, а не будет «не могу заранить / node не стартует».
**Определи тип и возьми стек — без вариантов:** **Определи тип и возьми стек — без вариантов:**
| Что хочет юзер | Стек (ЖЁСТКО) | Рецепт | | Что хочет юзер | Стек (ЖЁСТКО) | Навык / рецепт — загрузить ПЕРЕД работой |
|----------------|---------------|--------| |----------------|---------------|--------|
| Сайт, лендинг, визитка, портфолио, меню, афиша, waitlist | **Статика:** `index.html` + `style.css` + `script.js`, ванильный JS. БЕЗ сборки, БЕЗ React/Vue/Vite, БЕЗ npm. БЕЗ Tailwind/Bootstrap — вёрстка на дизайн-системе KT AI из `design-system/`. | старт с `design.md`, публикация в `pages` | | Сайт, лендинг, визитка, портфолио, меню, афиша, waitlist | **Статика:** в проекте УЖЕ лежит стартовый `index.html` на дизайн-системе KT AI — открой его (`read`) и правь (`edit`), не пиши с нуля; при необходимости + `script.js`. Ванильный JS, БЕЗ сборки, БЕЗ React/Vue/Vite, БЕЗ npm. БЕЗ Tailwind/Bootstrap/Google Fonts и без своих hex-цветов — только классы `kt-ai-*` и токены `var(--kt-ai-…)`. | навык `landing-templates` (шаблоны секций A–E) + `design.md` → правка готового `index.html`, публикация в `pages` |
| Telegram-бот | **Node.js (CommonJS) + grammY** (предустановлен), long-polling | Рецепт T ниже | | Telegram-бот | **Node.js (CommonJS) + grammY** (предустановлен), long-polling | навык `backend-run` → Рецепт T |
| Приложение с сервером: форма→сохраняет, API, дашборд с данными, счётчик, запись на время | **Node.js (CommonJS), сервер на `node:http` БЕЗ зависимостей + хранение в `data.json`** | Рецепт B ниже | | Приложение с сервером: форма→сохраняет, API, дашборд с данными, счётчик, запись на время | **Node.js (CommonJS), сервер на `node:http` БЕЗ зависимостей + хранение в `data.json`** | навык `backend-run` → Рецепт B |
| Нужен ИИ внутри (умный бот, генерация текста, ответы) | тот же Node-скелет + **`fetch` к `process.env.AI_BASE_URL`** (без SDK) | блок «ИИ» ниже | | Нужен ИИ внутри (умный бот, генерация текста, ответы) | тот же Node-скелет + **`fetch` к `process.env.AI_BASE_URL`** (без SDK) | навык `backend-run` → блок «ИИ» |
| Корпоративный агент Alem внутри проекта | тот же Node-скелет + вызов Alem по `process.env.ALEM_*` | раздел «Агент Alem» | | Корпоративный агент Alem внутри проекта | тот же Node-скелет + вызов Alem по `process.env.ALEM_*` | навык `backend-run` → раздел «Агент Alem» |
| **Презентация, слайды, «сделай презу», PowerPoint, pptx, доклад** | **СТАТИКА: ОДИН `index.html` + pptxgenjs с CDN. Бэкенд НЕ поднимать, ИИ в рантайме НЕ звать** | раздел «ПРЕЗЕНТАЦИИ» — бери оттуда скелет целиком | | **Презентация, слайды, «сделай презу», PowerPoint, pptx, доклад** | **СТАТИКА: ОДИН `index.html` + pptxgenjs с CDN. Бэкенд НЕ поднимать, ИИ в рантайме НЕ звать** | навык `presentations` — бери оттуда скелет целиком |
| Разобрать документы юзера (Excel / Word / PDF): свод, отчёт, выжимка | Предустановленные `xlsx` / `mammoth` / `pdf-parse` | раздел «ПРОЕКТ ПРИНИМАЕТ ФАЙЛЫ ЮЗЕРОВ» | | Разобрать документы юзера (Excel / Word / PDF): свод, отчёт, выжимка | Предустановленные `xlsx` / `mammoth` / `pdf-parse` | навык `office-files` |
| **Учёт и трекер:** склад, заявки, журнал, задачи, СИЗ, путевые листы, сбор статистики, отчётность | **Node.js + `node:http` + `data.json`** — тот же Рецепт B, но несколько сущностей и статусы | Рецепт B + «УЧЁТНАЯ СИСТЕМА» ниже | | **Учёт и трекер:** склад, заявки, журнал, задачи, СИЗ, путевые листы, сбор статистики, отчётность | **Node.js + `node:http` + `data.json`** — тот же Рецепт B, но несколько сущностей и статусы | навыки `backend-run` (Рецепт B) + `accounting-system` |
| Читать корпоративную почту юзера (Лотус) | Node-скелет + `process.env.LOTUS_*` | раздел «бот, читающий почту (Lotus)» | | Читать корпоративную почту юзера (Лотус) | Node-скелет + `process.env.LOTUS_*` | навык `backend-run` → «бот, читающий почту (Lotus)» |
**Сначала таблица, потом код.** Прежде чем писать хоть строку — найди в таблице строку под запрос юзера и открой указанный рецепт. Если запрос похож на два типа сразу (например «сайт, который делает презентации») — **выигрывает более простой стек**: презентация это статика, а не «приложение с сервером». Бэкенд поднимай, только когда без него физически никак: нужен Telegram-бот, приём данных от многих людей или хранение между устройствами. **Сначала таблица, потом код.** Прежде чем писать хоть строку — найди в таблице строку под запрос юзера и загрузи указанный навык вызовом `skill({ name: "..." })`: рецепты и скелеты лежат там, а не здесь. Если запрос похож на два типа сразу (например «сайт, который делает презентации») — **выигрывает более простой стек**: презентация это статика, а не «приложение с сервером». Бэкенд поднимай, только когда без него физически никак: нужен Telegram-бот, приём данных от многих людей или хранение между устройствами.
**Язык бэкенда — ВСЕГДА Node.js в стиле CommonJS: `require(...)`, а не `import`.** Не смешивай ESM и CJS — это главная причина «node не запускается». Python бери ТОЛЬКО если задача реально требует python-библиотеку, которой нет в JS (тогда `main.py` + `requirements.txt`). По умолчанию — Node. **Язык бэкенда — ВСЕГДА Node.js в стиле CommonJS: `require(...)`, а не `import`.** Не смешивай ESM и CJS — это главная причина «node не запускается». Python бери ТОЛЬКО если задача реально требует python-библиотеку, которой нет в JS (тогда `main.py` + `requirements.txt`). По умолчанию — Node.
@ -43,351 +41,39 @@ Workspace юзера `Aibek`. Это **учебная среда**, где об
3. Запуск бэкенда — ТОЛЬКО командой `run`. Никогда сам `node ...` / `npm start` в шелле. 3. Запуск бэкенда — ТОЛЬКО командой `run`. Никогда сам `node ...` / `npm start` в шелле.
--- ---
## 🍳 Готовые рецепты кода → навык `backend-run`
## 🍳 ГОТОВЫЕ РЕЦЕПТЫ (скопируй и поменяй только содержание) Скелеты, которые надо копировать целиком: Рецепт T (Telegram-бот на grammY), Рецепт B (сервер на `node:http` + `data.json`), блок «ИИ» без ключей — лежат в навыке `backend-run`. Прежде чем писать хоть строку бэкенда, вызови `skill({ name: "backend-run" })` и бери скелет оттуда, из головы не сочиняй.
### Рецепт T — Telegram-бот (Node + grammY, long-polling)
Спроси у юзера токен от @BotFather (одно сообщение). Создай 3 файла в текущей папке:
**`package.json`:**
```json
{
"name": "bot",
"private": true,
"type": "commonjs",
"scripts": { "start": "node --env-file=.env bot.js" }
}
```
(`grammy` уже предустановлен в контейнере — в `dependencies` его писать НЕ надо.)
**`bot.js`:**
```js
const { Bot } = require("grammy");
const bot = new Bot(process.env.BOT_TOKEN);
bot.command("start", (ctx) => ctx.reply("Привет! Я бот. Напиши мне что-нибудь."));
bot.on("message:text", (ctx) => ctx.reply("Ты написал: " + ctx.message.text));
bot.start();
console.log("Бот запущен (long-polling)");
```
**`.env`:** (токен сюда, в код НЕ хардкодить, в чат НЕ показывать)
```
BOT_TOKEN=сюда_токен_от_BotFather
```
**`.gitignore`:**
```
.env
node_modules/
.vibe42-run.log
.vibe42-run.pid
```
Затем `run`. Дай юзеру имя бота, скажи «напиши боту в Telegram /start». Бот без порта — это нормально (long-polling). НЕ используй webhooks.
**ВАЖНО:** `run` НЕ загружает `.env` сам — поэтому в `scripts.start` стоит `node --env-file=.env bot.js` (это грузит `.env` в окружение). Без `--env-file` бот упадёт с `Empty token!`. Если видишь `Empty token!` — проверь, что в `package.json` именно `node --env-file=.env bot.js` и что `.env` рядом с `bot.js`.
**НИКОГДА не пиши `require("node-fetch")` / `import fetch from "node-fetch"`.** В нашем Node 20 `fetch` уже глобальный, а пакет `node-fetch` НЕ установлен — эта строка роняет бота с `Cannot find module 'node-fetch'` (MODULE_NOT_FOUND). Вызывай просто `fetch(...)` без импорта. То же для любого HTTP из бота (Alem, Lotus, Telegram file API) — только голый `fetch`.
### Рецепт B — Приложение с сервером и хранением (Node + node:http, БЕЗ зависимостей)
Самый надёжный вариант: сервер на стандартной библиотеке Node — ставить нечего, значит и ломаться на зависимостях нечему. Данные хранятся в `data.json`. Фронт — статичный `index.html`, который ходит в API через `fetch`.
**`package.json`:**
```json
{
"name": "app",
"private": true,
"type": "commonjs",
"scripts": { "start": "node server.js" }
}
```
**`server.js`:**
```js
const http = require("http");
const fs = require("fs");
const path = require("path");
const PORT = process.env.PORT || 3000;
const DATA = path.join(__dirname, "data.json");
function readItems() {
try { return JSON.parse(fs.readFileSync(DATA, "utf8")); } catch (_) { return []; }
}
function writeItems(items) {
fs.writeFileSync(DATA, JSON.stringify(items, null, 2));
}
function body(req) {
return new Promise((resolve) => {
let s = "";
req.on("data", (c) => (s += c));
req.on("end", () => { try { resolve(JSON.parse(s || "{}")); } catch (_) { resolve({}); } });
});
}
http.createServer(async (req, res) => {
// API: список записей
if (req.method === "GET" && req.url === "/api/items") {
res.writeHead(200, { "Content-Type": "application/json" });
return res.end(JSON.stringify(readItems()));
}
// API: добавить запись
if (req.method === "POST" && req.url === "/api/items") {
const item = await body(req);
const items = readItems();
items.push({ id: Date.now(), ...item });
writeItems(items);
res.writeHead(200, { "Content-Type": "application/json" });
return res.end(JSON.stringify({ ok: true }));
}
// Статика: index.html / style.css / script.js
let file = req.url === "/" ? "/index.html" : req.url.split("?")[0];
const full = path.join(__dirname, file);
if (full.startsWith(__dirname) && fs.existsSync(full) && fs.statSync(full).isFile()) {
const ext = path.extname(full);
const type = ext === ".css" ? "text/css" : ext === ".js" ? "application/javascript" : "text/html";
res.writeHead(200, { "Content-Type": type + "; charset=utf-8" });
return res.end(fs.readFileSync(full));
}
res.writeHead(404); res.end("Not found");
}).listen(PORT, () => console.log("Сервер на порту " + PORT));
```
**`index.html`** — статичный фронт, который дёргает API (так Предпросмотр покажет актуальную вёрстку):
```html
<!doctype html>
<html lang="ru"><head><meta charset="utf-8"><title>Приложение</title></head>
<body>
<h1>Записи</h1>
<form id="f"><input name="text" placeholder="Новая запись" required><button>Добавить</button></form>
<ul id="list"></ul>
<script>
async function load() {
const items = await fetch("/api/items").then(r => r.json());
document.getElementById("list").innerHTML = items.map(i => "<li>" + i.text + "</li>").join("");
}
document.getElementById("f").addEventListener("submit", async (e) => {
e.preventDefault();
const text = e.target.text.value;
await fetch("/api/items", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ text }) });
e.target.reset(); load();
});
load();
</script>
</body></html>
```
`.gitignore`: `data.json`, `node_modules/`, `.vibe42-run.log`, `.vibe42-run.pid`. Затем `run` → дай юзеру ссылку из вывода ЦЕЛИКОМ (с `?t=...`).
### Блок «ИИ» — умный ответ БЕЗ ключей и БЕЗ SDK
Нужен ИИ в боте/приложении? НЕ проси ключ и НЕ ставь `openai` — ходи обычным `fetch` (ставить нечего, ломаться нечему). `AI_*` уже в окружении после `run`:
```js
async function ai(text) {
const r = await fetch(process.env.AI_BASE_URL + "/chat/completions", {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: "Bearer " + process.env.AI_API_KEY },
body: JSON.stringify({ model: process.env.AI_MODEL, messages: [{ role: "user", content: text }] })
});
if (!r.ok) throw new Error("ИИ недоступен, код " + r.status);
const j = await r.json();
const out = j.choices?.[0]?.message?.content;
if (!out) throw new Error("ИИ вернул пустой ответ");
return out;
}
```
В боте: `bot.on("message:text", async (ctx) => ctx.reply(await ai(ctx.message.text)));`. Ключ подставляется автоматически при `run` и живёт долго — просить его у юзера НЕ надо.
**⚠️ ЖЕЛЕЗНОЕ ПРАВИЛО: сбой ИИ показывай честно.** Если вызов ИИ упал — покажи юзеру понятную ошибку («ИИ временно недоступен, попробуйте ещё раз»). **НИКОГДА не подменяй ответ ИИ самодельной заглушкой** (нарезкой текста, случайными фразами, «рыбой»): юзер получит мусор и будет думать, что это и есть работа ИИ, а причину никто не найдёт. Лучше явная ошибка, чем тихая подделка.
--- ---
## 📥 ФАЙЛЫ ДЛЯ ЮЗЕРА (Excel, Word, отчёты) — создал, теперь ОТДАЙ ## 📥 Файлы для юзера (Excel, Word, отчёты) → навык `office-files`
Юзер просит «сделай отчёт», «выгрузи в эксель», «сформируй документ»? Файл мало создать — юзер должен его забрать. «Сделай отчёт», «выгрузи в эксель», «сформируй документ» — вызови `skill({ name: "office-files" })`: как сгенерировать файл и как ОТДАТЬ его юзеру. Создать файл мало — без выдачи юзер его не получит.
**Нужен Excel — бери команду `makexlsx`.** Она в твоём шелле, как `readdoc`, и делает настоящую книгу `.xlsx`: кириллица не ломается, шапка выделена и закреплена, ширина колонок по содержимому, числа остаются числами, даты — датами.
```bash
# из CSV, который ты сам собрал
makexlsx Отчёт_июль.xlsx --from data.csv --sheet "Июль"
# из JSON — можно сразу несколько листов
echo '{"Июль":[["Показатель","Значение"],["Пользователей",89]],
"Август":[["Задача","Статус"],["Миграция","в плане"]]}' | makexlsx Свод.xlsx
```
Принимает три вида JSON: строки `[[...],[...]]`, массив объектов `[{"Дата":"07.07"}, ...]` (ключи становятся шапкой) и словарь листов `{"Имя листа": [[...]]}`.
**Проверь результат** — прочитай созданный файл обратно: `readdoc Отчёт_июль.xlsx`.
**Правило имени: НЕ подделывай формат.**
- **НИКОГДА не клей двойное расширение** (`Otchet.xlsx.csv`, `report.docx.txt`). Excel откроет такой файл кракозябрами и предупредит о потере данных — юзер решит, что платформа сломана.
- Не используешь `makexlsx` — тогда честный `.csv` и **так и назови**, с BOM (`\uFEFF` в начале), иначе кириллица поедет.
- Внутри САЙТА (кнопка «Выгрузить в Excel» на странице) команда недоступна — там либо CSV с BOM, либо SheetJS с CDN.
**Правило выдачи: ВСЕГДА скажи, где скачать.** Создал файл — следующей же фразой напиши юзеру:
> Готово, файл `Otchet.xlsx` лежит в проекте. Открой вкладку **Файлы** справа и нажми **«Скачать»** напротив него.
Без этой фразы юзер файл не найдёт — он не знает, что вкладка «Файлы» существует.
**Не предлагай** юзеру «скопируй код и запусти у себя», «открой терминал», «склонируй репозиторий» — он пришёл за готовым файлом, а не за инструкцией по разработке.
--- ---
## 📊 УЧЁТНАЯ СИСТЕМА (склад, заявки, журнал, задачи, СИЗ, путевые листы) ## 📊 Учётная система → навык `accounting-system`
Юзер просит «вести учёт», «трекер», «журнал», «заявки», «склад», «отчёт по сотрудникам»? Это Рецепт B, но с несколькими сущностями и статусами. Не изобретай схему — бери эту. Склад, заявки, журнал, задачи, СИЗ, путевые листы, учёт и отчётность — сначала вызови `skill({ name: "accounting-system" })` (модель `data.json`, поля, статусы, экраны), потом строй по Рецепту B из навыка `backend-run`. Схему не изобретай.
**Модель данных — один файл `data.json`, внутри списки:**
```js
// { "items": [...], "log": [...] } // items — то, что учитываем; log — история действий
const EMPTY = { items: [], log: [] };
function load() { try { return JSON.parse(fs.readFileSync(DATA, "utf8")); } catch { return EMPTY; } }
function save(d) { fs.writeFileSync(DATA, JSON.stringify(d, null, 2)); }
```
**Каждая запись — минимум эти поля** (добавь свои по задаче юзера):
```js
{ id: Date.now(), title: "Каска защитная", qty: 12, person: "Иванов И.",
status: "выдано", // статусы бери из слов юзера, не выдумывай английские
date: new Date().toISOString().slice(0, 10),
note: "" }
```
**Обязательный минимум экранов** (иначе юзер не сможет пользоваться):
1. **Таблица** всех записей + строка поиска (фильтр по подстроке на клиенте).
2. **Форма добавления** — та же форма редактирует запись (кнопка «Изменить» подставляет значения).
3. **Фильтр по статусу** — кнопки-чипсы над таблицей.
4. **Счётчики сверху**: всего / по каждому статусу.
5. **Кнопка «Выгрузить в Excel»** — юзеру почти всегда нужно унести данные:
```js
// на клиенте, без библиотек: CSV с BOM открывается в Excel сразу и не ломает кириллицу
function exportCsv(rows) {
const head = ["Наименование", "Кол-во", "Ответственный", "Статус", "Дата"];
const body = rows.map(r => [r.title, r.qty, r.person, r.status, r.date]
.map(v => '"' + String(v ?? "").replace(/"/g, '""') + '"').join(";"));
const csv = "\uFEFF" + [head.join(";"), ...body].join("\n");
const a = document.createElement("a");
a.href = URL.createObjectURL(new Blob([csv], { type: "text/csv" }));
a.download = "vygruzka.csv"; a.click();
}
```
**Правила, без которых учёт бесполезен:**
- Удаление — только через `confirm()`, и запись уходит в `log`, а не исчезает бесследно.
- Любое изменение пишет строку в `log`: `{ when, what, who }` — юзер обязательно спросит «кто менял».
- Даты показывай как `ДД.ММ.ГГГГ`, хранить можно как есть.
- Если юзер назвал сущность по-своему («СИЗ», «путевой лист») — так и называй её в интерфейсе, не заменяй на «items»/«записи».
--- ---
## 📂 ПРОЕКТ ПРИНИМАЕТ ФАЙЛЫ ЮЗЕРОВ (Excel / Word / PDF) — библиотеки УЖЕ установлены ## 📂 Проект принимает файлы юзеров → навык `office-files`
В контейнере проекта ПРЕДУСТАНОВЛЕНЫ (НЕ добавляй их в dependencies и НЕ ставь — просто require): В проекте нужна загрузка Excel / Word / PDF / CSV и разбор их на сервере — сначала вызови `skill({ name: "office-files" })`: предустановленные библиотеки (`xlsx`, `mammoth`, `pdf-parse`), приём файла и рецепты чтения. Свои парсеры не пиши.
- **Node:** `grammy` (бот), `xlsx` (Excel/CSV), `mammoth` (Word → текст/HTML), `pdf-parse` (PDF → текст), `formidable` (загрузка файлов в приложении).
- **Python:** `openpyxl`, `python-docx`, `pypdf`, `requests`.
Всё, чего в списке нет, — добавляй в `dependencies`, поставит `run`.
**Разобрать файл (Node):**
```js
// Excel → массив объектов
const XLSX = require("xlsx");
function readExcel(path) {
const wb = XLSX.readFile(path);
return XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
}
// Word → текст
const mammoth = require("mammoth");
async function readWord(path) { return (await mammoth.extractRawText({ path })).value; }
// PDF → текст
const fs = require("fs");
const pdfParse = require("pdf-parse");
async function readPdf(path) { return (await pdfParse(fs.readFileSync(path))).text; }
```
**Бот принимает файл от юзера (grammY):** файл надо скачать с серверов Telegram, потом разбирать:
```js
bot.on("message:document", async (ctx) => {
const file = await ctx.getFile();
const url = "https://api.telegram.org/file/bot" + process.env.BOT_TOKEN + "/" + file.file_path;
const buf = Buffer.from(await (await fetch(url)).arrayBuffer());
const name = ctx.message.document.file_name || "file";
if (name.endsWith(".xlsx") || name.endsWith(".xls")) {
const wb = require("xlsx").read(buf);
const rows = require("xlsx").utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
return ctx.reply("Строк в таблице: " + rows.length);
}
if (name.endsWith(".docx")) {
const t = (await require("mammoth").extractRawText({ buffer: buf })).value;
return ctx.reply("Текст из Word (начало): " + t.slice(0, 300));
}
if (name.endsWith(".pdf")) {
const t = (await require("pdf-parse")(buf)).text;
return ctx.reply("Текст из PDF (начало): " + t.slice(0, 300));
}
ctx.reply("Пока умею: .xlsx, .docx, .pdf");
});
```
**Приложение принимает загрузку файла (formidable + node:http):** добавь в server.js из Рецепта B:
```js
const formidable = require("formidable");
// внутри createServer, перед статикой:
if (req.method === "POST" && req.url === "/api/upload") {
const form = formidable({ uploadDir: __dirname, keepExtensions: true });
form.parse(req, (err, fields, files) => {
const f = files.file && files.file[0];
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ ok: !err && !!f, path: f ? f.filepath : null }));
});
return;
}
```
Во фронте: `<input type="file">` + `FormData` + `fetch("/api/upload", { method: "POST", body: formData })`. Дальше разбирай файл рецептами выше и отвечай юзеру данными.
--- ---
## 🚑 НЕ ЗАПУСКАЕТСЯ? ЧЕК-ЛИСТ (симптом → причина → фикс) ## 🚑 Не запускается? → навык `backend-run`
Прежде чем гадать — открой `run logs` и найди строку с ошибкой, потом по таблице: Бэкенд не стартует, `run` падает, пустой экран, ошибка в логах — открой `run logs`, найди строку с ошибкой и вызови `skill({ name: "backend-run" })`: там чек-лист «симптом → причина → фикс». Не гадай без него.
| Симптом в логах / у юзера | Причина | Фикс |
|---------------------------|---------|------|
| `SyntaxError: Cannot use import statement` | написал `import` (ESM) | переведи на `require(...)` (CommonJS). У нас по умолчанию CommonJS. |
| `run` пишет «не нашёл, что запускать» | нет `package.json` со `scripts.start` и нет `bot.js`/`server.js` | добавь `package.json` с `"scripts": {"start": "node bot.js"}` (или `server.js`) |
| `Error: Cannot find module 'X'` | зависимости `X` нет в `package.json` | добавь `X` в `dependencies`, запусти `run` заново (он поставит). НЕ `npm install` в шелле |
| `Cannot find module` для предустановленного (grammy/xlsx/mammoth/pdf-parse/formidable) | старый контейнер | добавь пакет в `dependencies` и `run` заново — сработает в любом случае |
| приложение запустилось, но не отвечает / порт | слушаешь не тот порт | слушай ровно `process.env.PORT || 3000` |
| `Empty token!` / бот не видит токен | `.env` не загружается | в `package.json` → `"start": "node --env-file=.env bot.js"`; `.env` рядом с `bot.js` |
| бот не отвечает в Telegram | используешь webhook | только `bot.start()` (long-polling), НЕ webhooks; токен в `.env` → `process.env.BOT_TOKEN` |
| `401` / ИИ не отвечает | протух AI-ключ (или хардкод) | не хардкодь ключ; запусти `run` заново — освежит `AI_*` |
| ссылка из `run` перестала открываться | контейнер уснул (20 мин простоя) | просто `run` заново — поднимется |
| Предпросмотр пустой у проекта с сервером | превью показывает статику | у бэкенда рабочая ссылка — из `run`; фронт держи статичным (`index.html` + `fetch` к API) |
Правило второго захода: упало — прочитай `run logs`, найди симптом в таблице, поправь ОДНУ вещь, снова `run`. Не переписывай всё с нуля.
--- ---
## 📎 ФАЙЛЫ ОТ ЮЗЕРА (Excel, Word, CSV, текст) ## 📎 Файлы от юзера → навык `office-files`
Юзер может прикрепить файл — он ложится в папку проекта. **Читать Excel/Word напрямую (`cat`) нельзя** — они бинарные (zip+xml). Для извлечения текста используй хостовую команду **`readdoc <файл>`** (в твоём шелле):
- `readdoc data.xlsx` — все листы Excel как таблицы (значения через табуляцию);
- `readdoc doc.docx` — текст Word по абзацам;
- `readdoc doc.pdf` — текст из PDF (сканы без текстового слоя не прочтёт);
- `readdoc table.csv` / `.tsv` / `.txt` — как есть (можно и `cat`);
- большой файл — ограничь: `readdoc big.xlsx --max 100`.
Юзер просит «проанализируй таблицу/документ» → вызови `readdoc`, разбери вывод и ответь по сути (сводка, цифры, что нашёл). Команда `readdoc` — только для ТВОЕГО анализа в чате; в код запущенного проекта её не вставляй (в контейнере её нет).
**Не нашёл файл в текущей папке?** Загруженный файл мог лечь в КОРЕНЬ воркспейса (на уровень выше cwd). Проверь `ls ..` и читай/копируй оттуда: `readdoc "../имя файла.xlsx"` или `cp "../имя.xlsx" .`. Не переспрашивай юзера «где файл» раньше, чем глянешь в родительскую папку. Юзер прислал Excel, Word, CSV или текст и просит разобрать, свести, посчитать — вызови `skill({ name: "office-files" })` ДО того, как открывать файл: там где его искать и чем читать.
**Используй ВСЕ данные, не «первые N».** Если строишь из файла таблицу/список/каталог — выведи ВСЕ записи, а не 5-6. **НИКОГДА не проси юзера «допишите остальные строки вручную»** — это твоя работа. Данных много (десятки+ строк)? НЕ хардкодь сотни `<tr>` в HTML (модель обрежет вывод): сохрани данные рядом файлом `data.json` (массив объектов) и отрисуй в `index.html` через JS — `fetch('data.json').then(r=>r.json()).then(rows => …)` + `map`/`innerHTML`. Так отрисуются все строки, и появится место для поиска/фильтра. `readdoc` при большом файле зови с запасом (`--max 1000`), чтобы получить все строки.
--- ---
@ -404,14 +90,12 @@ if (req.method === "POST" && req.url === "/api/upload") {
4. Собирай страницу **прямо в текущей папке проекта** — ты уже в ней (проект создан за тебя). Создавай `index.html`/`style.css`/`script.js` тут же. **НЕ запускай `./new-project`** и не делай `cd` в другие папки. Не спрашивай разрешения на каждый шаг. 4. Собирай страницу **прямо в текущей папке проекта** — ты уже в ней (проект создан за тебя). Создавай `index.html`/`style.css`/`script.js` тут же. **НЕ запускай `./new-project`** и не делай `cd` в другие папки. Не спрашивай разрешения на каждый шаг.
--- ---
## 👀 Предпросмотр — говори про него юзеру ## 👀 Предпросмотр — говори про него юзеру
- Справа в интерфейсе есть вкладка **Предпросмотр** — она сама показывает сайт юзера и обновляется при каждом изменении файлов. Когда начинаешь собирать сайт, скажи один раз: «Смотри на вкладку Предпросмотр справа — там сайт появится и будет обновляться на глазах». - Справа в интерфейсе есть вкладка **Предпросмотр** — она сама показывает сайт юзера и обновляется при каждом изменении файлов. Когда начинаешь собирать сайт, скажи один раз: «Смотри на вкладку Предпросмотр справа — там сайт появится и будет обновляться на глазах».
- Когда сайт опубликован, ВСЕГДА завершай отдельной строкой: «🎉 Готово! Твой сайт: <ссылка>» и добавь: «Нажми Поделиться в панели предпросмотра — там ссылка и QR-код, чтобы показать с телефона». - Когда сайт опубликован, ВСЕГДА завершай отдельной строкой: «🎉 Готово! Твой сайт: <ссылка>» и добавь: «Нажми Поделиться в панели предпросмотра — там ссылка и QR-код, чтобы показать с телефона».
--- ---
## 🧠 Память о юзере — веди её сам ## 🧠 Память о юзере — веди её сам
Файл памяти: `/srv/opencode/workspaces/users/Aibek/.mimo/memory.md` (dot-папка `.mimo` не видна в Предпросмотре — так и задумано). Папка `.mimo/` уже создана, тебе нужно только читать/писать `memory.md`. Файл памяти: `/srv/opencode/workspaces/users/Aibek/.mimo/memory.md` (dot-папка `.mimo` не видна в Предпросмотре — так и задумано). Папка `.mimo/` уже создана, тебе нужно только читать/писать `memory.md`.
@ -438,7 +122,6 @@ if (req.method === "POST" && req.url === "/api/upload") {
**Это касается ВСЕГО видимого текста, а не только финального ответа.** Промежуточные комментарии между вызовами инструментов — планы («сейчас найду нужную строку…»), статусы («добавляю кнопки в hero…»), мысли вслух — юзер их ЧИТАЕТ, и они обязаны быть на его языке. Писать «We'll edit line 139» русскоязычному юзеру — ошибка. По-английски остаются только код, команды и имена файлов. **Это касается ВСЕГО видимого текста, а не только финального ответа.** Промежуточные комментарии между вызовами инструментов — планы («сейчас найду нужную строку…»), статусы («добавляю кнопки в hero…»), мысли вслух — юзер их ЧИТАЕТ, и они обязаны быть на его языке. Писать «We'll edit line 139» русскоязычному юзеру — ошибка. По-английски остаются только код, команды и имена файлов.
--- ---
## 💬 ЕСЛИ ЮЗЕР ОТВЕЧАЕТ РАСПЛЫВЧАТО ## 💬 ЕСЛИ ЮЗЕР ОТВЕЧАЕТ РАСПЛЫВЧАТО
Юзер говорит «сделай что-нибудь» / «ну хз» / «сюрприз» → **не делай ничего абстрактного**. Юзер говорит «сделай что-нибудь» / «ну хз» / «сюрприз» → **не делай ничего абстрактного**.
@ -451,7 +134,6 @@ if (req.method === "POST" && req.url === "/api/upload") {
После ответов **сразу** предложи 2 конкретных варианта названия+структуры. Дай выбрать и иди делать. После ответов **сразу** предложи 2 конкретных варианта названия+структуры. Дай выбрать и иди делать.
--- ---
## 🧭 ВЕДИ ЮЗЕРА ПО ЕГО ИДЕЕ — НЕ ПОДМЕНЯЙ ЕЁ ## 🧭 ВЕДИ ЮЗЕРА ПО ЕГО ИДЕЕ — НЕ ПОДМЕНЯЙ ЕЁ
**НЕ уговаривай юзера на «лендинг вместо» его идеи.** Если он хочет бота, магазин или приложение — помоги сделать именно это, по-настоящему. Твоя задача — провести человека по ЕГО идее до работающего результата, а не продать ему заглушку попроще. **НЕ уговаривай юзера на «лендинг вместо» его идеи.** Если он хочет бота, магазин или приложение — помоги сделать именно это, по-настоящему. Твоя задача — провести человека по ЕГО идее до работающего результата, а не продать ему заглушку попроще.
@ -473,115 +155,15 @@ if (req.method === "POST" && req.url === "/api/upload") {
4. **Не говори «у нас только статические сайты»** — это больше неправда: бэкенды запускаются через `run`. 4. **Не говори «у нас только статические сайты»** — это больше неправда: бэкенды запускаются через `run`.
--- ---
## 📐 Шаблоны страниц → навык `landing-templates`
## 📐 ШАБЛОНЫ СТРАНИЦ (выбирай под идею юзера) Лендинг, визитка, портфолио, афиша, меню, прайс, waitlist — вызови `skill({ name: "landing-templates" })` и возьми готовую структуру секций (шаблоны A–E) под идею юзера, потом правь `index.html`.
### 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-форма).
Все шаблоны — **одна страница, прокрутка вниз**. Никаких роутов, ничего динамического.
--- ---
## 🎤 ПРЕЗЕНТАЦИИ («сделай презу из этих доков») ## 🎤 Презентации → навык `presentations`
Юзер кидает документы и просит презентацию? Флоу: «Сделай презу», слайды, PowerPoint, pptx, доклад из документов — сначала вызови `skill({ name: "presentations" })`: там флоу и готовый скелет `index.html` с pptxgenjs по CDN. Свой генератор pptx не выдумывай, бэкенд не поднимай.
1. Прочитай доки командой `readdoc` (умеет .xlsx, .docx, .pdf, .csv/.txt). Файлы могут лежать в корне воркспейса — проверь `ls ..`.
2. Выдели суть: 5-9 слайдов, на слайде заголовок + 3-5 коротких пунктов. Не переноси абзацы целиком — сжимай до тезисов.
3. Возьми скелет ниже (это ОДИН файл `index.html`) и поменяй ТОЛЬКО массив `SLIDES` — он рисует и слайды в браузере, и настоящий PowerPoint по кнопке «Скачать .pptx». Остальной код не трогай.
4. Покажи через Предпросмотр (стрелки/клавиши листают). Публикация — как обычный сайт, по кнопке «Опубликовать»: юзер получает ссылку, открывает с проектора/телефона.
5. Скажи юзеру: «Кнопка Скачать .pptx внизу — настоящий PowerPoint; печать страницы (Ctrl+P) — PDF, слайд на страницу».
Скелет (файл `index.html`, целиком):
```html
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Презентация</title>
<script src="https://cdn.jsdelivr.net/npm/pptxgenjs@3.12.0/dist/pptxgen.bundle.js"></script>
<style>
* { margin: 0; box-sizing: border-box; }
body { font-family: -apple-system, "Segoe UI", Roboto, sans-serif; background: #0f1218; color: #f4f4f5; }
.slide { display: none; min-height: 100vh; padding: 8vh 10vw; flex-direction: column; justify-content: center; }
.slide.on { display: flex; }
.slide h1 { font-size: clamp(34px, 6vw, 64px); margin-bottom: 24px; }
.slide li { font-size: clamp(18px, 2.6vw, 28px); line-height: 1.6; margin-bottom: 10px; list-style: none; padding-left: 28px; position: relative; }
.slide li::before { content: ""; position: absolute; left: 0; top: .55em; width: 12px; height: 12px; border-radius: 3px; background: #00b8cc; }
.num { position: fixed; bottom: 18px; right: 22px; color: #8a8a92; font-size: 14px; }
.nav { position: fixed; bottom: 14px; left: 22px; display: flex; gap: 8px; }
.nav button { border: 1px solid #333; background: #171719; color: #f4f4f5; border-radius: 8px; padding: 8px 14px; cursor: pointer; font-size: 14px; }
.nav .pptx { border-color: #00b8cc; color: #9beeff; }
@media print {
.nav, .num { display: none; }
.slide { display: flex; page-break-after: always; min-height: 100vh; }
}
</style>
</head>
<body>
<div id="deck"></div>
<div class="nav">
<button onclick="go(-1)">Назад</button>
<button onclick="go(1)">Вперёд</button>
<button class="pptx" onclick="downloadPptx()">Скачать .pptx</button>
</div>
<div class="num" id="num"></div>
<script>
// ============ ВСЁ СОДЕРЖАНИЕ ПРЕЗЕНТАЦИИ — ТОЛЬКО В ЭТОМ МАССИВЕ ============
var SLIDES = [
{ title: "Название презентации", bullets: ["Подзаголовок или одна ключевая мысль", "Автор / дата"] },
{ title: "Проблема", bullets: ["Пункт один", "Пункт два", "Пункт три"] },
{ title: "Решение", bullets: ["Что предлагаем", "Как это работает"] },
{ title: "Итоги", bullets: ["Главный вывод", "Следующий шаг"] }
];
// ============================================================================
var cur = 0;
function render() {
var deck = document.getElementById("deck");
deck.innerHTML = SLIDES.map(function (s, i) {
return '<section class="slide' + (i === cur ? " on" : "") + '"><h1>' + s.title + '</h1><ul>' +
s.bullets.map(function (b) { return "<li>" + b + "</li>"; }).join("") + "</ul></section>";
}).join("");
document.getElementById("num").textContent = (cur + 1) + " / " + SLIDES.length;
}
function go(d) { cur = Math.min(SLIDES.length - 1, Math.max(0, cur + d)); render(); }
document.addEventListener("keydown", function (e) {
if (e.key === "ArrowRight" || e.key === " ") go(1);
if (e.key === "ArrowLeft") go(-1);
});
function downloadPptx() {
var p = new PptxGenJS();
p.defineLayout({ name: "W", width: 13.33, height: 7.5 });
p.layout = "W";
SLIDES.forEach(function (s) {
var sl = p.addSlide();
sl.background = { color: "0F1218" };
sl.addText(s.title, { x: 0.7, y: 0.5, w: 12, h: 1.2, fontSize: 36, bold: true, color: "F4F4F5" });
sl.addText(s.bullets.map(function (b) { return { text: b, options: { bullet: true, breakLine: true } }; }),
{ x: 0.9, y: 2.0, w: 11.5, h: 4.8, fontSize: 20, color: "E4E4E7", lineSpacingMultiple: 1.4 });
});
p.writeFile({ fileName: "presentation.pptx" });
}
render();
</script>
</body>
</html>
```
Правила: цвета/шрифты можно подгонять под тему юзера в `<style>`; фото — через ссылки picsum/loremflickr (см. design.md); НЕ выдумывай свой pptx-генератор и НЕ ставь pptxgenjs в проект — он уже подключён с CDN в скелете.
--- ---
@ -601,7 +183,6 @@ render();
4. Дальше короткие итерации: правка → `git commit` → `git push origin HEAD:main` → показывай в Предпросмотре. Каждые 2-3 правки — commit. 4. Дальше короткие итерации: правка → `git commit` → `git push origin HEAD:main` → показывай в Предпросмотре. Каждые 2-3 правки — commit.
--- ---
## 🚀 ПУБЛИКАЦИЯ В ИНТЕРНЕТ — ТОЛЬКО ПО КНОПКЕ «Опубликовать» ## 🚀 ПУБЛИКАЦИЯ В ИНТЕРНЕТ — ТОЛЬКО ПО КНОПКЕ «Опубликовать»
**Публикуй (push в ветку `pages`) ТОЛЬКО когда юзер явно просит опубликовать.** Он нажимает кнопку **«Опубликовать»** вверху — тебе приходит сообщение вида «Опубликуй текущий проект…». САМ, без такой просьбы, в `pages` НИКОГДА не пушь — как бы хорошо сайт ни выглядел. **Публикуй (push в ветку `pages`) ТОЛЬКО когда юзер явно просит опубликовать.** Он нажимает кнопку **«Опубликовать»** вверху — тебе приходит сообщение вида «Опубликуй текущий проект…». САМ, без такой просьбы, в `pages` НИКОГДА не пушь — как бы хорошо сайт ни выглядел.
@ -618,7 +199,6 @@ git push origin HEAD:pages
и добавь: «Нажми Поделиться в панели предпросмотра — там ссылка и QR-код». и добавь: «Нажми Поделиться в панели предпросмотра — там ссылка и QR-код».
--- ---
## ⚠️ ЖЕЛЕЗНЫЕ ПРАВИЛА (НЕ нарушать никогда) ## ⚠️ ЖЕЛЕЗНЫЕ ПРАВИЛА (НЕ нарушать никогда)
1. **Дефолт — статика (HTML + CSS + JS).** Сайты и лендинги собирай статикой, публикация через `pages`. 1. **Дефолт — статика (HTML + CSS + JS).** Сайты и лендинги собирай статикой, публикация через `pages`.
@ -629,121 +209,9 @@ git push origin HEAD:pages
6. **НИКОГДА `git init` в workspace root (`/srv/opencode/workspaces/users/Aibek`)** — это папка-контейнер юзера, не репозиторий. 6. **НИКОГДА `git init` в workspace root (`/srv/opencode/workspaces/users/Aibek`)** — это папка-контейнер юзера, не репозиторий.
--- ---
## ⚙️ Бэкенд, боты, run → навык `backend-run`
## ⚙️ БЭКЕНД-ПРОЕКТЫ (telegram-бот, API, динамика) — команда `run` Telegram-бот, API, сервер, команда `run`, динамика, ИИ или агент Alem внутри проекта, корпоративная почта Lotus — сначала вызови `skill({ name: "backend-run" })` (рецепты T и B, блок «ИИ», Alem, почта, чек-лист «не запускается»), потом строй. Без него не начинай.
Юзер хочет бота или приложение с сервером? Это МОЖНО. Не отговаривай и не подменяй лендингом-визиткой. Флоу:
1. Пиши код в текущей папке проекта. Node: `package.json` (со `scripts.start`) + `server.js`; Python: `bot.py`/`main.py` + `requirements.txt`. Слушай порт `process.env.PORT || 3000`.
2. Запусти командой **`run`** (просто `run` в шелле). Она сама поставит зависимости и запустит процесс в изолированном контейнере юзера (2 ГБ RAM). Первая установка может идти пару минут — предупреди юзера.
3. Из вывода `run` возьми ссылку и дай юзеру **ЦЕЛИКОМ, включая `?t=...`**. Сам ссылку НЕ конструируй: нет вывода `run` — нет ссылки.
4. Отладка: `run logs` (лог приложения), `run status`, `run stop`. Упало — читай `run logs`, чини, снова `run`.
5. Процесс засыпает после ~20 минут простоя. Это нормально: файлы сохраняются, повторный `run` поднимает всё снова. Скажи юзеру об этом честно.
6. **Telegram-бот:** только long-polling через **grammY** (готовый скелет — Рецепт T выше), НЕ вебхуки. Попроси у юзера токен от @BotFather, положи в `.env`, читай из `process.env` — токен НИКОГДА не коммить и не показывать в чате.
7. Добавь в `.gitignore`: `.env`, `.vibe42-run.log`, `.vibe42-run.pid`, `node_modules/`.
8. Вкладка Предпросмотр показывает только статические файлы — для бэкенда живая ссылка приходит из `run`, публикация в `pages` для бэкенда не нужна.
9. **Команды `lotus` / `vibe42` / `run` доступны ТОЛЬКО в ТВОЁМ шелле (ИИ-сессии), НЕ внутри запущенного проекта.** Код бота/приложения крутится в изолированном контейнере, где этих команд НЕТ — вызов `lotus`/`vibe42` через `exec`/`child_process`/`subprocess` даст `command not found` и сломает бота. Данные из Лотуса/корп-сервисов внутри юзерского бота пока НЕ поддерживаются — не обещай их и не шелли туда, делай бота на том, что реально доступно (ИИ через `process.env.AI_*`, публичные API).
### 🤖 ИИ внутри проекта юзера — БЕЗ ключей, автоматически
Если бот/приложение юзера должен обращаться к ИИ — **НЕ проси у юзера никакой ключ** (ни OpenAI `sk-…`, ни из «Интеграции»). При запуске через `run` в окружении проекта УЖЕ есть свежий доступ — подставляется сам:
- `process.env.AI_BASE_URL`, `process.env.AI_API_KEY`, `process.env.AI_MODEL` — уже в окружении, обновляются при каждом `run`.
- Подключай любым OpenAI-SDK: `new OpenAI({ baseURL: process.env.AI_BASE_URL, apiKey: process.env.AI_API_KEY })`, модель `process.env.AI_MODEL`. Python — так же (`OpenAI(base_url=..., api_key=...)`).
- **НЕ пиши `AI_*` в `.env` и НЕ спрашивай ключ у юзера** — они придут из окружения при `run`. Не хардкодь, не логируй. Если в `.env` уже что-то есть — не трогай, `run` всё равно перекроет свежим.
- Ключ подставляется автоматически при `run` и живёт долго — просить его у юзера НЕ надо.
**⚠️ ЖЕЛЕЗНОЕ ПРАВИЛО: сбой ИИ показывай честно.** Если вызов ИИ упал — покажи юзеру понятную ошибку («ИИ временно недоступен, попробуйте ещё раз»). **НИКОГДА не подменяй ответ ИИ самодельной заглушкой** (нарезкой текста, случайными фразами, «рыбой»): юзер получит мусор и будет думать, что это и есть работа ИИ, а причину никто не найдёт. Лучше явная ошибка, чем тихая подделка.
### 🧠 Агент Alem (корпоративный ИИ-агент)
**Alem** — корпоративная платформа КТ, где юзер сам создаёт, проверяет и публикует ИИ-агента под свою задачу. Опубликованного агента можно подключить к продукту, собранному в Vibe42, и вызывать как ИИ-функцию внутри продукта (чат, кнопка, после формы, шаг процесса, черновик/проверка/рекомендация). **Vibe42 НЕ создаёт агента за юзера** — юзер делает его в Alem, а Vibe42 только подключает и встраивает вызов.
Флоу: юзер открывает **Интеграции → Агент Alem**, вводит название, Open API key (`sk-...`) и «Выделенный сотрудник ID» (оба из окна API-ключа одного и того же опубликованного агента), сохраняет. При `run` в окружении проекта появляются `process.env.ALEM_BASE_URL` (уже указывает на локальный Alem-прокси платформы), `process.env.ALEM_API_KEY` (ключ `sk-...`) и `process.env.ALEM_TEMPLATE_ID`. Не появились — Alem не подключён, скажи юзеру открыть **Интеграции → Агент Alem**.
**СНАЧАЛА проверь агента ПРЯМО ИЗ ЧАТА — не бросайся строить телеграм-бота!** Во фразе «подключись к моему Алем боту» слово «бот» означает самого Alem-агента, а НЕ Telegram. Порядок:
1. Выполни в bash из папки проекта: `alem-ask "Привет! Расскажи коротко, что ты умеешь?"` — команда сама найдёт подключённого к проекту агента и напечатает его ответ. Покажи ответ юзеру. Любые «спроси у агента…» делай так же — через alem-ask, без написания кода.
2. Если команда ответила «Alem не подключён» — попроси юзера открыть «Интеграции → Агент Alem», сохранить ключ и ID сотрудника, затем повтори alem-ask.
3. Спроси юзера, ГДЕ использовать агента: на сайте, в telegram-боте или пока просто спрашивать из чата. Telegram-бота строй ТОЛЬКО после явного выбора юзера («да, давай в телеграм»).
⚡ **КОМАНДА @alem.** Если сообщение юзера начинается с `@alem` — всё, что после, это вопрос напрямую его Alem-агенту. НЕМЕДЛЕННО, без рассуждений, планов и создания файлов, выполни в bash: `alem-ask "<текст после @alem>"` и верни вывод команды юзеру ДОСЛОВНО, ничего не добавляя от себя. Пример: юзер пишет «@alem какие форматы файлов ты принимаешь?» → ты выполняешь `alem-ask "какие форматы файлов ты принимаешь?"` → отвечаешь тем, что напечатала команда.
**Как вызывать API (ТОЛЬКО с серверной стороны проекта, ключ не логировать/не отдавать в браузер):**
1. Создать сессию: `POST ${process.env.ALEM_BASE_URL}/api/v1/open-api/conversation` с заголовком `Authorization: Bearer ${process.env.ALEM_API_KEY}`, тело `{"template_id": process.env.ALEM_TEMPLATE_ID, "title": "Vibe42", "user_id": "<стабильный id юзера>"}` → ответ JSON вида `{"code":200,"data":{"session_id":"..."}}`; ⚠️ session_id лежит ВНУТРИ поля `data` (в JS: `body.data.session_id`, НЕ `body.session_id`).
2. Отправить запрос: `POST ${process.env.ALEM_BASE_URL}/api/v1/open-api/conversation/<SESSION_ID>/send`, тот же заголовок, тело `{"content":"<запрос>","user_id":"<id>","model_api_key": process.env.ALEM_API_KEY}` → ответ приходит **SSE-потоком** (строки `data: {...}`). ⚠️ НЕ вызывай `resp.json()` — упадёт с «Unexpected token 'd'». Итоговый текст — в событии `message_result`, поле `detail.full_content`.
```js
// Готовый рабочий код Alem — копируй КАК ЕСТЬ, не переписывай и не сокращай:
async function createAlemSession() {
const url = process.env.ALEM_BASE_URL + "/api/v1/open-api/conversation";
const resp = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json", "Authorization": "Bearer " + process.env.ALEM_API_KEY },
body: JSON.stringify({ template_id: process.env.ALEM_TEMPLATE_ID, title: "Vibe42", user_id: "vibe42_user" })
});
if (!resp.ok) throw new Error("Alem create " + resp.status + ": " + (await resp.text()));
const body = await resp.json();
const sid = body && body.data && body.data.session_id; // session_id ВНУТРИ поля data!
if (!sid) throw new Error("Alem не вернул session_id: " + JSON.stringify(body).slice(0, 200));
return sid;
}
async function askAlem(sessionId, message) {
const url = process.env.ALEM_BASE_URL + "/api/v1/open-api/conversation/" + sessionId + "/send";
const resp = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json", "Authorization": "Bearer " + process.env.ALEM_API_KEY },
body: JSON.stringify({ content: message, user_id: "vibe42_user", model_api_key: process.env.ALEM_API_KEY })
});
if (!resp.ok) throw new Error("Alem " + resp.status + ": " + (await resp.text()));
const raw = await resp.text(); // SSE-поток: resp.json() здесь СЛОМАЕТСЯ
let answer = null;
for (const line of raw.split("\n")) {
const s = line.trim();
if (!s.startsWith("data:")) continue;
const payload = s.slice(5).trim();
if (!payload || payload === "[DONE]") continue;
try {
const ev = JSON.parse(payload);
if (ev && ev.detail && typeof ev.detail.full_content === "string" && ev.detail.full_content) {
answer = ev.detail.full_content;
}
} catch (e) {}
}
return answer || "Нет ответа";
}
// Обычно нужно именно это: создать сессию и спросить.
async function runAlem(prompt) {
return askAlem(await createAlemSession(), prompt);
}
```
Этот код проверен вживую и работает — не изобретай свой разбор ответа.
Ошибки: `403 OpenAPI key has no permission for this resource` — ключ и «Выделенный сотрудник ID» от РАЗНЫХ агентов, возьми оба из одного опубликованного агента; `model_api_key is required` — передай `model_api_key` в теле `send`; НЕ используй старые пути `/api/v1/published/...` — они больше не работают.
Правила: используй только подключённого к ЭТОМУ проекту агента; ключ никогда не показывай в коде/логах/предпросмотре; рискованные действия от имени юзера — только по явному сценарию. Для создания агента направляй юзера на https://wiki.ai-kt.kz.
### 📧 РЕЦЕПТ: бот, читающий почту юзера (Lotus)
Юзер просит бота, который читает его письма — делай СТРОГО по шагам, порядок важен:
**Шаг 1 — сперва подключение, потом код.** Ответь: «Сделаю! Сначала подключи почту: вверху **Интеграции → Лотус**, вставь токен, нажми «Подключить». Как подключишь — напиши «готово».» И ЖДИ подтверждения. НЕ пиши бота и НЕ запускай, пока юзер не подтвердил — иначе бот стартует без доступа к почте.
**Шаг 2 — после «готово».** Спроси токен Telegram-бота у @BotFather (если ещё не давал), положи в `.env`. Затем напиши бота. Почту читай ТОЛЬКО HTTP-запросом к нашему прокси — команду `lotus` из кода НЕ вызывай (её в контейнере нет). Готовый паттерн `/inbox` (node, скопируй и адаптируй):
```js
async function inbox() {
if (!process.env.LOTUS_BASE_URL) return 'Почта не подключена — открой «Интеграции → Лотус».';
const res = await fetch(process.env.LOTUS_BASE_URL + '/emails?folder=inbox&count=5', {
headers: { Authorization: 'Bearer ' + process.env.LOTUS_API_KEY } });
const j = await res.json();
if (!j.ok) return 'Не удалось получить письма: ' + (j.error || 'ошибка');
return 'Последние письма:\n' + (j.data || []).slice(0,5).map(m =>
(m.read === false ? '🔵 ' : '') + (m.date||'').slice(0,10) +
(m.from?.displayName ? ' — ' + m.from.displayName : '') + ': ' + (m.subject||'(без темы)').trim()
).join('\n');
}
```
Другие маршруты того же прокси (заголовок тот же): `/email/<unid>` (одно письмо), `/folders`, `/whoami`, `/contacts?q=имя`. Только ЧТЕНИЕ. `LOTUS_API_KEY`/`LOTUS_BASE_URL` берутся ИЗ ОКРУЖЕНИЯ — токен у юзера текстом НЕ спрашивай и в код не хардкодь.
**Шаг 3 — запуск.** `run`, дай юзеру имя бота, скажи «напиши боту /inbox». Если в логах `LOTUS_BASE_URL` пуст — значит Лотус не подключён: попроси подключить в «Интеграции» и запусти `run` ЗАНОВО (env подхватывается при запуске).
--- ---
@ -764,7 +232,6 @@ async function inbox() {
4. В server.js путь запроса очищай от query: сравнивай `req.url.split("?")[0]`, а не весь req.url — иначе ссылка с параметрами отдаст 404. 4. В server.js путь запроса очищай от query: сравнивай `req.url.split("?")[0]`, а не весь req.url — иначе ссылка с параметрами отдаст 404.
5. Если есть бэкенд — запусти `run` и ДОЧИТАЙ лог до конца: ошибка в логе = фаза не сдана. Если только статика — посмотри вкладку Предпросмотр. 5. Если есть бэкенд — запусти `run` и ДОЧИТАЙ лог до конца: ошибка в логе = фаза не сдана. Если только статика — посмотри вкладку Предпросмотр.
6. Никаких выдуманных CDN-адресов и библиотек: используй только то, что перечислено в рецептах ниже. 6. Никаких выдуманных CDN-адресов и библиотек: используй только то, что перечислено в рецептах ниже.
## 📁 ТЫ УЖЕ ВНУТРИ ПАПКИ ПРОЕКТА — собирай сайт ЗДЕСЬ ## 📁 ТЫ УЖЕ ВНУТРИ ПАПКИ ПРОЕКТА — собирай сайт ЗДЕСЬ
Твоя рабочая директория (cwd) — это **папка проекта юзера** (`.../users/<username>/<project>/`). Проект уже создан за тебя в тот момент, когда юзер написал идею на главной. Проверь: `pwd` — папка проекта, `ls` — там лежат AGENTS.md/design.md/README.md. Твоя рабочая директория (cwd) — это **папка проекта юзера** (`.../users/<username>/<project>/`). Проект уже создан за тебя в тот момент, когда юзер написал идею на главной. Проверь: `pwd` — папка проекта, `ls` — там лежат AGENTS.md/design.md/README.md.
@ -779,7 +246,6 @@ async function inbox() {
Только если юзер ЯВНО просит **отдельный НОВЫЙ проект** («создай ещё один проект», «сделай новый сайт отдельно») — и только тогда, когда в текущей папке реально есть скрипт `new-project` (значит ты в корне воркспейса). В обычном сценарии «сделай мне лендинг» — НЕ нужен, собирай в текущей папке. Только если юзер ЯВНО просит **отдельный НОВЫЙ проект** («создай ещё один проект», «сделай новый сайт отдельно») — и только тогда, когда в текущей папке реально есть скрипт `new-project` (значит ты в корне воркспейса). В обычном сценарии «сделай мне лендинг» — НЕ нужен, собирай в текущей папке.
--- ---
## 🌐 Git и публикация ## 🌐 Git и публикация
**НЕТ GitHub.** Self-hosted git: **https://git.vibe42.kz** **НЕТ GitHub.** Self-hosted git: **https://git.vibe42.kz**
@ -802,7 +268,6 @@ git push origin HEAD:pages
**Если push отклонён («permission denied for writing» и т.п.)** — это проблема git-кредов, она чинится сама при перезаходе. Скажи юзеру ровно это: «Перезайди на платформу (выйди и войди) и нажми "Опубликовать" ещё раз». НИКОГДА не связывай ошибки git/публикации с Лотусом — Лотус это ТОЛЬКО корпоративная почта, к репозиториям и публикации он отношения не имеет. Не выдумывай причин, которых не видишь в выводе команды. **Если push отклонён («permission denied for writing» и т.п.)** — это проблема git-кредов, она чинится сама при перезаходе. Скажи юзеру ровно это: «Перезайди на платформу (выйди и войди) и нажми "Опубликовать" ещё раз». НИКОГДА не связывай ошибки git/публикации с Лотусом — Лотус это ТОЛЬКО корпоративная почта, к репозиториям и публикации он отношения не имеет. Не выдумывай причин, которых не видишь в выводе команды.
--- ---
## 🔧 Когда что-то идёт не так ## 🔧 Когда что-то идёт не так
- **Pages 404** → запушь ветку `pages` снова: `git push origin HEAD:pages -f` - **Pages 404** → запушь ветку `pages` снова: `git push origin HEAD:pages -f`
@ -818,7 +283,6 @@ git push origin HEAD:pages
- Запуталось — сделай новый чистый проект через `./new-project NAME-v2`, перенеси туда работающий index.html - Запуталось — сделай новый чистый проект через `./new-project NAME-v2`, перенеси туда работающий index.html
--- ---
## ❌ Чего НЕ делать НИКОГДА ## ❌ Чего НЕ делать НИКОГДА
- ❌ `git init` в workspace root - ❌ `git init` в workspace root
@ -838,11 +302,12 @@ git push origin HEAD:pages
- ❌ Зависать в обсуждениях — сделай первый вариант грубо, потом итерируй - ❌ Зависать в обсуждениях — сделай первый вариант грубо, потом итерируй
--- ---
## 🎨 design.md + дизайн-система KT AI ## 🎨 design.md + дизайн-система KT AI
Рядом лежит `design.md` — **прочитай его перед первой строкой вёрстки**. В нём каркас `index.html`, классы блоков лендинга и токены дизайн-системы KT AI, которая уже лежит в проекте папкой `design-system/`. Рядом лежит `design.md` — **прочитай его перед первой строкой вёрстки**. В нём каркас `index.html`, классы блоков лендинга и токены дизайн-системы KT AI, которая уже лежит в проекте папкой `design-system/`.
**Порядок для сайта/страницы — ровно такой:** 1) `read design.md`, 2) `read index.html` — стартовый каркас на ДС уже лежит в проекте, 3) `edit index.html` под задачу юзера. Отдельный `style.css` со своей палитрой не нужен: ДС уже стилизует кнопки, карточки и типографику; свой `<style>` — только на мелочи, и цвета в нём — токенами `var(--kt-ai-…)`. Запись HTML/CSS с Tailwind/Bootstrap/Google Fonts или с россыпью hex-цветов отклоняется автоматически (design-guard) — не спорь с ним и не обходи через bash, а исправь файл. Если проект не про веб-страницу (бот, скрипт, разбор документов) — стартовый `index.html` просто удали.
Правило простое: **весь UI собирается из классов и токенов ДС**. Свои цвета, шрифты и чужие CSS-фреймворки (Bootstrap, Tailwind, Material, Font Awesome, Google Fonts) — не подключаем: в ДС уже всё есть, включая шрифт Inter. Правило простое: **весь UI собирается из классов и токенов ДС**. Свои цвета, шрифты и чужие CSS-фреймворки (Bootstrap, Tailwind, Material, Font Awesome, Google Fonts) — не подключаем: в ДС уже всё есть, включая шрифт Inter.
Папку `design-system/` коммить вместе с проектом — иначе опубликованная на Pages страница останется без стилей. Папку `design-system/` коммить вместе с проектом — иначе опубликованная на Pages страница останется без стилей.

417
batys-shygys-turik.html Normal file
View File

@ -0,0 +1,417 @@
<!-- no-design-system -->
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Батыс және Шығыс Түрік қағанаттары</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⚔️</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Батыс және Шығыс Түрік қағанаттары</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">60</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 60</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "Қазақстан тарихында VI–IX ғасырларды қамтитын кезең қалай аталады?", options: ["Ежелгі дәуір", "Ерте орта ғасыр", "Дамыған орта ғасыр", "Кейінгі орта ғасыр"], correct: 1 },
{ q: "Түрік қағанаты қай жылы екіге бөлінді?", options: ["552 жылы", "603 жылы", "610 жылы", "682 жылы"], correct: 1 },
{ q: "Түрік қағанатының екіге бөлінуінің негізгі себептерінің бірі:", options: ["Арабтардың шапқыншылығы", "Моңғолдардың шабуылы", "Ішкі талас-тартыс және Қытай шапқыншылығы", "Егіншіліктің тоқтауы"], correct: 2 },
{ q: "Батыс түркілердің өз мемлекетін құруының саяси себебі қандай болды?", options: ["Сауда жолдарын бақылау", "Қаған әулеттерінің дербес билікке ұмтылуы", "Мал шаруашылығын дамыту", "Қытаймен бейбіт келісім жасау"], correct: 1 },
{ q: "Батыс түркілердің жеке мемлекет құруының экономикалық себебі:", options: ["Әр өлкенің шаруашылық ерекшелігі", "Қытайдың салық саясаты", "Сауда жолдарының жабылуы", "Қалалардың жойылуы"], correct: 0 },
{ q: "Батыс Түрік қағанатының халқы қандай бірлестікке бірікті?", options: ["Үш жүз", "Тоғыз оғыз", "Он оқ тайпа одағы", "Қарлұқ бірлестігі"], correct: 2 },
{ q: "«Он оқ» жүйесінде бір тайпа қанша әскер шығарды?", options: ["5 мың", "10 мың", "20 мың", "50 мың"], correct: 1 },
{ q: "Әр «оқты» кім басқарды?", options: ["Тудун", "Шад", "Қолбасы", "Би"], correct: 2 },
{ q: "Әр «оқтың» қандай ерекшелігі болды?", options: ["Өз қаласы болды", "Өз әскери жалауы болды", "Өз теңгесі болды", "Өз ордасы болды"], correct: 1 },
{ q: "Батыс Түрік қағанатының аумақтық өзегі қай жерде қалыптасты?", options: ["Алтайда", "Жетісуда", "Моңғолияда", "Сырдарияның төменгі ағысында"], correct: 1 },
{ q: "Батыс Түрік қағанатының қысқы ордасы орналасқан қала:", options: ["Баласағұн", "Тараз", "Суяб", "Испиджаб"], correct: 2 },
{ q: "Суяб қаласы қай өзеннің алқабында орналасты?", options: ["Іле", "Ертіс", "Шу", "Сырдария"], correct: 2 },
{ q: "Батыс Түрік қағанатының жазғы ордасы орналасқан жер:", options: ["Мыңбұлақ", "Өтікен", "Суяб", "Қаратау"], correct: 0 },
{ q: "Мыңбұлақ қай жердің маңында орналасқан?", options: ["Тараз", "Түркістан", "Алматы", "Балқаш"], correct: 1 },
{ q: "Жетісу Батыс Түрік қағанатының аумақтық өзегіне айналуының басты себебі:", options: ["Мұнда алтын кендері көп болды", "Барлық керуен жолдары түйісті", "Қытай астанасына жақын болды", "Тек мал шаруашылығы дамыды"], correct: 1 },
{ q: "«Он оқ бұдун» тайпаларының қаншасы Дулу тайпасынан тұрды?", options: ["3", "4", "5", "7"], correct: 2 },
{ q: "«Он оқ бұдун» құрамындағы Нушеби тайпаларының саны:", options: ["2", "3", "5", "10"], correct: 2 },
{ q: "Дулу тайпалары негізінен қай аймақта орналасты?", options: ["Шу өзенінің батысында", "Шу өзенінің шығысында", "Сырдарияның батысында", "Каспий теңізінің маңында"], correct: 1 },
{ q: "Нушеби тайпалары мекендеген аймақ:", options: ["Шу өзенінің батысы", "Шу өзенінің шығысы", "Алтайдың шығысы", "Іленің солтүстігі"], correct: 0 },
{ q: "Қытай деректерінде Иштеми қаған қалай аталды?", options: ["Ұлы қаған", "Он тайпа қағаны", "Шығыс қағаны", "Жетісу қағаны"], correct: 1 },
{ q: "Иштеми қағанның әскері қанша адам болған?", options: ["50 мың", "70 мың", "100 мың", "200 мың"], correct: 2 },
{ q: "Л.Н. Гумилевтің зерттеуінше, Иштеми қағаннан кейін билікке кім келді?", options: ["Тон-ябғу", "Шегу", "Тардуш Дато", "Ешбар Елтеріс"], correct: 2 },
{ q: "Батыс Түрік қағанатының алғашқы қағаны:", options: ["Иштеми", "Тардуш Дато", "Шегу", "Тон-ябғу"], correct: 1 },
{ q: "Тардуш Дато тұсында қандай тарихи жағдай орын алды?", options: ["Қағанат Қытайға тәуелді болды", "Батыс Түрік қағанаты түпкілікті жеке мемлекетке айналды", "Түрік қағанаты қайта құрылды", "Ашина әулеті жойылды"], correct: 1 },
{ q: "Батыс Түрік қағанаты қай қағандар тұсында VII ғасырдың бірінші жартысында өркендеді?", options: ["Құтлық пен Қапаған", "Білге мен Күлтегін", "Шегу мен Тон-ябғу", "Тардуш пен Иштеми"], correct: 2 },
{ q: "Шегу қаған қай жылдары билік құрды?", options: ["552–603 жж.", "610–618 жж.", "618–630 жж.", "716–731 жж."], correct: 1 },
{ q: "Тон-ябғу қағанның билік құрған жылдары:", options: ["603–610 жж.", "610–618 жж.", "618–630 жж.", "630–650 жж."], correct: 2 },
{ q: "Тон-ябғу тұсында Орталық Азия мемлекеттеріне қандай жағдай қалыптасты?", options: ["Қағанаттың бақылауынан шықты", "Қатаң бақылау орнықты", "Қытайға қосылды", "Тәуелсіз мемлекеттерге айналды"], correct: 1 },
{ q: "Тон-ябғу қаған қол астындағы иеліктерге кімдерді жіберді?", options: ["Шадтарды", "Тудундарды", "Қолбасшыларды", "Билерді"], correct: 1 },
{ q: "Қытай шежірешісі Тон-ябғу билігі туралы қандай пікір айтты?", options: ["Түркілер әлсіз болды", "Батыс варварлары ешқашан дәл осындай қуатты болған жоқ", "Қағанат Қытайға тәуелді болды", "Түркілердің қалалары болмады"], correct: 1 },
{ q: "«Он тайпа – он оқ бұдун» жүйесін енгізген қаған:", options: ["Иштеми", "Тон-ябғу", "Ешбар Елтеріс", "Құтлық"], correct: 2 },
{ q: "«Он оқ бұдун» әскери жүйесінде барлығы қанша түмен болды?", options: ["5", "10", "20", "100"], correct: 1 },
{ q: "Бір түмендегі әскер саны:", options: ["1 мың", "5 мың", "10 мың", "20 мың"], correct: 2 },
{ q: "Батыс Түрік қағанатында қандай шаруашылық жүйесі біртұтас дамыды?", options: ["Тек көшпелі мал шаруашылығы", "Тек отырықшы егіншілік", "Көшпелі және отырықшы-егіншілік", "Тек қолөнер"], correct: 2 },
{ q: "Батыс Түрік қағанаты халқының негізгі кәсіптерінің бірі ЕМЕС:", options: ["Қолөнер", "Сауда", "Егіншілік", "Теңіз кәсіпшілігі"], correct: 3 },
{ q: "VI–VIII ғасырларда Шу алқабында шамамен қанша ірі қала мен қоныс болды?", options: ["5-ке жуық", "10-ға жуық", "20-ға жуық", "50-ге жуық"], correct: 2 },
{ q: "Шу алқабындағы қалаларда қоныстанған халықтардың бірі:", options: ["Түркілер", "Римдіктер", "Византиялықтар", "Славяндар"], correct: 0 },
{ q: "Батыс Түрік қағанатына тәуелді болған ортаазиялық мемлекеттерді анықтаңыз.", options: ["Хорезм, Ферғана, Шаш", "Қытай, Үндістан, Иран", "Хазар, Оғыз, Қимақ", "Соғды, Қытай, Моңғолия"], correct: 0 },
{ q: "Батыс Түрік қағанатында ақша соғу ісін кімдер жүзеге асырды?", options: ["Түркілер", "Парсылар", "Соғдылықтар", "Қытайлар"], correct: 2 },
{ q: "VII ғасырдағы Қытай саяхатшысы Жетісу туралы қандай мәлімет қалдырды?", options: ["Жер өңдеушілер мен қолөнершілердің көп екенін жазды", "Қалалардың толық қирағанын жазды", "Халықтың тек мал шаруашылығымен айналысқанын жазды", "Жетісуда халық болмағанын жазды"], correct: 0 },
{ q: "Түркі қағандары жаулап алынған жерлерде қандай саясат жүргізді?", options: ["Бұрынғы тәртіпті толығымен өзгертті", "Бұрыннан бар тәртіпті сақтап, салық алумен шектелді", "Халықты түгел көшірді", "Қалаларды қиратты"], correct: 1 },
{ q: "Қаған билігін әлсіреткен негізгі факторлардың бірі:", options: ["Қолөнердің дамуы", "Тайпалар арасындағы қырқыс", "Сауданың өсуі", "Қалалардың көбеюі"], correct: 1 },
{ q: "Батыс Түрік қағанатының әлсіреуін пайдаланған мемлекет:", options: ["Хазар қағанаты", "Қытайдың Таң империясы", "Оғыз мемлекеті", "Қимақ қағанаты"], correct: 1 },
{ q: "Батыс Түрік қағанатының орнына Жетісуда қандай мемлекет құрылды?", options: ["Оғыз мемлекеті", "Қимақ қағанаты", "Түргеш мемлекеті", "Хазар қағанаты"], correct: 2 },
{ q: "682 жылы қандай тарихи оқиға болды?", options: ["Батыс Түрік қағанаты құрылды", "Шығыс түркілер мемлекетін қайта құрды", "Хазар қағанаты жойылды", "Тон-ябғу билікке келді"], correct: 1 },
{ q: "Шығыс Түрік қағанаты қай аумақта құрылды?", options: ["Жетісуда", "Моңғолия аумағында", "Қазақстанның батысында", "Солтүстік Кавказда"], correct: 1 },
{ q: "Шығыс Түрік қағанатының орталығы:", options: ["Суяб", "Мыңбұлақ", "Өтікен", "Тараз"], correct: 2 },
{ q: "Шығыс Түрік қағанатының алғашқы қағаны:", options: ["Білге", "Құтлық", "Қапаған", "Күлтегін"], correct: 1 },
{ q: "716 жылы Шығыс Түрік қағанатының билеушісі болған:", options: ["Қапаған", "Құтлық", "Білге қаған", "Тон-ябғу"], correct: 2 },
{ q: "Білге қағанның інісі және Түрік қағанатын қайта өркендетуге үлес қосқан тұлға:", options: ["Иштеми", "Күлтегін", "Шегу", "Ешбар Елтеріс"], correct: 1 },
{ q: "744 жылы Шығыс Түрік қағанатын талқандаған күштер:", options: ["Қытай мен Хазарлар", "Оғыздар мен Қимақтар", "Ұйғыр және қарлұқ күштері", "Соғдылар мен парсылар"], correct: 2 },
{ q: "Шығыс Түрік қағанаты Қапаған қаған тұсында қай аймақты бағындырды?", options: ["Батыс Қазақстанды", "Орталық Азияны", "Жетісуды", "Солтүстік Кавказды"], correct: 1 },
{ q: "Білге қаған Қытайға қарсы қай жылы соғысты?", options: ["716 жылы", "723 жылы", "731 жылы", "744 жылы"], correct: 1 },
{ q: "Білге қағанның Қытаймен соғыстағы жеңісінің нәтижесі:", options: ["Қытай Түрік қағанатын жаулап алды", "Түріктер Қытайға толық тәуелді болды", "Ұтымды бейбіт келісімге қол жеткізілді", "Шығыс Түрік қағанаты жойылды"], correct: 2 },
{ q: "Қытай императоры Түрік ордасына не жіберді?", options: ["Алтын мен күміс", "Үлкен көлемде жібек", "Әскер мен қару", "Азық-түлік"], correct: 1 },
{ q: "Білге мен Күлтегінге арналған құлпытастар қай жерде орнатылды?", options: ["Шу өзені бойында", "Орхон өзені маңында", "Алтай тауларында", "Сырдария бойында"], correct: 1 },
{ q: "Шығыс Түрік қағанатының орталығы Өтікен қай жерде орналасты?", options: ["Алтай тауларында", "Хангай тауларында", "Қаратау тауларында", "Тянь-Шань тауларында"], correct: 1 },
{ q: "Білге қаған мен Күлтегін қай мемлекетті қайта өркендетті?", options: ["Батыс Түрік қағанатын", "Хазар қағанатын", "Түрік қағанатын", "Түргеш қағанатын"], correct: 2 },
{ q: "Күлтегін қай жылы дүние салды?", options: ["716 жылы", "723 жылы", "731 жылы", "744 жылы"], correct: 2 },
{ q: "Күлтегін қайтыс болғаннан кейін көп ұзамай кім дүние салды?", options: ["Қапаған қаған", "Білге қаған", "Құтлық қаған", "Тардуш Дато"], correct: 1 },
{ q: "744 жылы Шығыс Түрік қағанаты талқандалғаннан кейін қандай әулеттің өмір сүруі тоқтады?", options: ["Ашина әулеті", "Дулу әулеті", "Нушеби әулеті", "Қарлұқ әулеті"], correct: 0 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>

View File

@ -1,4 +1,4 @@
<!-- vibe42-design-version: v3-ktai-ds-2026-09-01 --> <!-- vibe42-design-version: v4-ds-scaffold-2026-09-11 -->
# Дизайн-система KT AI — по ней собирается весь UI # Дизайн-система KT AI — по ней собирается весь UI
В папке проекта лежит `design-system/` — это **дизайн-система KT AI** В папке проекта лежит `design-system/` — это **дизайн-система KT AI**
@ -31,6 +31,9 @@ cp -r /srv/opencode/design-system/kt-ai design-system
Это рабочий каркас лендинга. Копируй его целиком и меняй содержание. Это рабочий каркас лендинга. Копируй его целиком и меняй содержание.
**В новом проекте этот каркас уже лежит как `index.html`** — не создавай файл заново: `read index.html` → `edit`.
Если проект старый и файла нет — скопируй каркас ниже целиком. Если проект не про веб-страницу — стартовый `index.html` можно удалить.
```html ```html
<!DOCTYPE html> <!DOCTYPE html>
<html lang="ru" data-theme="auto"> <html lang="ru" data-theme="auto">

397
gun-imperiyasy.html Normal file
View File

@ -0,0 +1,397 @@
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Ғұн империясы</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏹</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
.topic-selector { display: flex; gap: var(--kt-ai-space-4); justify-content: center; margin-top: var(--kt-ai-space-6); flex-wrap: wrap; }
.topic-btn { min-width: 200px; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Ғұн империясы</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">40</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 40</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "Ғұн империясы көшпелілер тарихында қандай орын алады?", options: ["Екінші көшпелі мемлекет", "Алғашқы көшпелі империя", "Алғашқы отырықшы мемлекет", "Ең соңғы көшпелі мемлекет"], correct: 1 },
{ q: "Ғұндар туралы негізгі дерек беретін дереккөз:", options: ["Парсы деректері", "Рим деректері", "Қытай деректері", "Грек деректері"], correct: 2 },
{ q: "Ғұндар мемлекетінің қалыптасуына негізгі әсер еткен жағдай:", options: ["Теңіз саудасының дамуы", "Көршілес тайпалық одақтар мен Қытаймен күрес", "Егіншіліктің қарқынды дамуы", "Рим империясымен одақ құру"], correct: 1 },
{ q: "Ғұн мемлекетінің басында тұрған билеуші қалай аталды?", options: ["Қаған", "Патша", "Тәңірқұт (шаньюй)", "Хан"], correct: 2 },
{ q: "Тәңірқұттың билігі қалай берілді?", options: ["Сайлау арқылы", "Әскери кеңес арқылы", "Мұрагерлікпен", "Тайпа көсемдерінің шешімімен"], correct: 2 },
{ q: "Ғұндар Тәңірқұтты қалай атаған?", options: ["«Ұлы қаған»", "«Аспан ұлы»", "«Дала әміршісі»", "«Жер патшасы»"], correct: 1 },
{ q: "Төмендегілердің қайсысы Тәңірқұттың міндетіне жатты?", options: ["Тек діни рәсімдерді басқару", "Тек мал санағын жүргізу", "Соғыс жариялау және бітім жасау", "Тек жер үлестіру"], correct: 2 },
{ q: "Ғұн мемлекетінде Тәңірқұттан кейінгі жоғары тұлғалар:", options: ["Мыңбасылар", "Жүзбасылар", "Сол жақ және оң жақ Кіші хандар", "Ақсақалдар"], correct: 2 },
{ q: "Кіші хандар қандай аумақтарды басқарды?", options: ["Солтүстік және оңтүстік аумақтарды", "Батыс және шығыс аумақтарды", "Орталық және оңтүстік аумақтарды", "Тек шекаралық аймақтарды"], correct: 1 },
{ q: "Ғұн әскеріндегі 10 мыңдық әскерді басқарған лауазым:", options: ["Мыңбасы", "Жүзбасы", "Онбасы", "Түменбасы"], correct: 3 },
{ q: "Ғұн империясында қанша түменбасы болған?", options: ["12", "18", "24", "36"], correct: 2 },
{ q: "Түменбасылар кімдерден тағайындалды?", options: ["Қарапайым жауынгерлерден", "Шетелдік билеушілерден", "Шаньюйдың туысқандарынан", "Саудагерлерден"], correct: 2 },
{ q: "Түменбасыларды кім тағайындады?", options: ["Кіші хандар", "Тайпа ақсүйектері", "Шаньюй", "Мыңбасылар"], correct: 2 },
{ q: "Ғұн қоғамындағы ер адамдардың негізгі міндеткерлігі:", options: ["Егіншілікпен айналысу", "Әскери қызмет атқару", "Сауда жасау", "Мал санағын жүргізу"], correct: 1 },
{ q: "Әскери борыштан жалтарған ғұн жауынгеріне қандай жаза қолданылды?", options: ["Айыппұл салынды", "Жерінен айырылды", "Өлім жазасына кесілді", "Құлдыққа сатылды"], correct: 2 },
{ q: "Ғұндарда тайпалардың орын ауыстыруы қалай жүзеге асты?", options: ["Әр тайпа өз бетінше көшті", "Қытайдың рұқсатымен көшті", "Шаньюйдің бұйрығынсыз орын ауыстыруға тыйым салынды", "Кіші хандардың келісімімен ғана көшті"], correct: 2 },
{ q: "Кіші хандар мен түменбасылар жылына неше рет мемлекеттік істерді талқылау үшін жиналды?", options: ["Бір рет", "Екі рет", "Үш рет", "Төрт рет"], correct: 2 },
{ q: "Адамдар мен малдың санын есептеу және тексеру қашан жүргізілді?", options: ["Көктемде", "Жазда", "Қыста", "Күзде"], correct: 3 },
{ q: "Ғұн империясының билеуші тобы кімдерден құрылды?", options: ["Құлдардан", "Ру-тайпалық ақсүйектерден", "Саудагерлерден", "Егіншілерден"], correct: 1 },
{ q: "Ақсүйектердің саяси күші неге байланысты болды?", options: ["Әскер санына", "Сауда көлеміне", "Иелік еткен жайылымдық жерлеріне", "Қытаймен қарым-қатынасына"], correct: 2 },
{ q: "Ғұн империясының үш ғасырдан астам өмір сүруіне мүмкіндік берген фактор:", options: ["Теңіз флотының болуы", "Тұрақты саяси құрылым", "Риммен одақ", "Қытайға толық тәуелділік"], correct: 1 },
{ q: "Б.з.б. 209 жылы ғұн тайпаларының билігіне келген қолбасшы:", options: ["Аттилла", "Чжи-чжи", "Мөде", "Гаоди"], correct: 2 },
{ q: "Мөде б.з.б. 209 жылы қандай аймақтардағы тайпаларды жаулап алды?", options: ["Жетісу, Сырдария, Арал", "Саян, Алтай, Жоғарғы Енисей", "Дунай, Балқан, Карпат", "Бактрия, Парфия, Хорезм"], correct: 1 },
{ q: "Қытай деректеріндегі Мөде әскерінің саны:", options: ["100 мың", "200 мың", "300 мың", "500 мың"], correct: 2 },
{ q: "«Жер дегеніміз — мемлекеттің негізі, оны қалай береміз» деген сөзді айтқан ғұн билеушісі:", options: ["Аттилла", "Мөде", "Чжи-чжи", "У-ди"], correct: 1 },
{ q: "Ғұндардың басты қарсыластарының бірі болған көшпелі мемлекет:", options: ["Үйсін", "Қаңлы", "Юэчжи", "Кушан"], correct: 2 },
{ q: "Б.з.б. 200 жылдары ғұндарға қарсы жорыққа шыққан Қытай императоры:", options: ["У-ди", "Гаоди", "Цинь Шихуанди", "Чжи-чжи"], correct: 1 },
{ q: "Гаоди ғұндармен бейбіт келісім жасау үшін не істеді?", options: ["Ғұндарға жер берді", "Қытай ханшайымын Мөдеге берді", "Ғұндарға әскер жіберді", "Юэчжилермен одақ құрды"], correct: 1 },
{ q: "Ғұндар мен юэчжилер арасындағы соғыс немен аяқталды?", options: ["Қытайдың жеңісімен", "Үйсіндердің жеңісімен", "Ғұндардың толық жеңісімен", "Бейбіт келісіммен"], correct: 2 },
{ q: "Ғұндар мен юэчжилер арасындағы соғыс б.з.б. қай жылы аяқталды?", options: ["209 жылы", "200 жылы", "165 жылы", "133 жылы"], correct: 2 },
{ q: "Б.з.б. II ғасырда ғұндардың қысымымен Солтүстік-Батыс Қытайдан Шығыс және Оңтүстік-Шығыс Қазақстанға қоныстанған тайпа:", options: ["Үйсіндер", "Қаңлылар", "Юэчжилер", "Сарматтар"], correct: 2 },
{ q: "Б.з.б. 47–46 жылдары солтүстік ғұн билеушісіне үйсіндерге қарсы күресте қолдау көрсеткен тайпа:", options: ["Юэчжилер", "Қаңлылар", "Сақтар", "Сарматтар"], correct: 1 },
{ q: "Б.з.б. I ғасырдың ортасында ғұндар қандай екі бөлікке бөлінді?", options: ["Шығыс және Батыс", "Солтүстік және Оңтүстік", "Орталық және Шеткі", "Жоғарғы және Төменгі"], correct: 1 },
{ q: "Батысқа қарай жылжыған солтүстік ғұндар II ғасырдың ортасында қандай мемлекет құрды?", options: ["Кушан", "Қаңлы", "Юэбань", "Үйсін"], correct: 2 },
{ q: "Ғұн тайпаларының әлемдік тарихи үдерістерге тигізген басты ықпалы:", options: ["Ұлы Жібек жолын қалыптастырды", "Ұлы қоныс аударуын бастады", "Кушан патшалығын құрды", "Қытай империясын жойды"], correct: 1 },
{ q: "V ғасырда Шығыс Еуропада өз мемлекетін құрған ғұндардың ұлы көсемі:", options: ["Мөде", "Чжи-чжи", "Аттилла", "Гаоди"], correct: 2 },
{ q: "Аттилла өз мемлекетін қай жерде құрды?", options: ["Орталық Азияда", "Шығыс Еуропада", "Қытайда", "Бактрияда"], correct: 1 },
{ q: "Аттилла басқарған ғұндар қай империяның үстемдігінен Еуропаны азат етті?", options: ["Қытай империясының", "Кушан империясының", "Рим империясының", "Парсы империясының"], correct: 2 },
{ q: "Дунайға дейін жетіп, Венгрияға қоныстанған тайпа:", options: ["Юэчжилер", "Үйсіндер", "Қаңлылар", "Ғұндар"], correct: 3 },
{ q: "Ғұндардың Еуропаға жасаған жорықтарының тарихи салдарының бірі:", options: ["Ұлы Жібек жолының тоқтауы", "Ұлы қоныс аударудың басталуы", "Кушан патшалығының құрылуы", "Қытайдың бірігуі"], correct: 1 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>

View File

@ -53,7 +53,7 @@
<section class="kt-ai-hero" data-align="center"> <section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap"> <div class="kt-ai-wrap">
<h1>Ұлы Дала мәдениеті</h1> <h1>Ұлы Дала мәдениеті</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және ҰБТ-ға жақсылап дайындал</p> <p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;"> <div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field"> <div class="kt-ai-field">
@ -125,7 +125,7 @@
</section> </section>
<footer class="kt-ai-wrap kt-ai-pagefoot"> <footer class="kt-ai-wrap kt-ai-pagefoot">
<span>© 2026 ҰБТ: Қазақстан тарихы</span> <span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span> <span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span> <span>Сәттілік тілейміз!</span>
</footer> </footer>
@ -176,6 +176,16 @@ let timerInterval = null;
let seconds = 0; let seconds = 0;
let userName = ''; let userName = '';
let answered = false; let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() { function checkLogin() {
const savedName = localStorage.getItem('ebtUserName'); const savedName = localStorage.getItem('ebtUserName');
@ -244,13 +254,14 @@ function startQuiz() {
currentQuestion = 0; currentQuestion = 0;
answers = {}; answers = {};
seconds = 0; seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer(); startTimer();
document.getElementById('q-total').textContent = QUESTIONS.length; document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion(); showQuestion();
} }
function showQuestion() { function showQuestion() {
const q = QUESTIONS[currentQuestion]; const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1; document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q; document.getElementById('question-text').textContent = q.q;
@ -338,15 +349,16 @@ function showResults() {
let correct = 0; let correct = 0;
let wrong = 0; let wrong = 0;
QUESTIONS.forEach((q, i) => { shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) { const originalIndex = QUESTIONS.findIndex(orig => orig.q === q.q);
if (answers[i] === originalIndex) {
correct++; correct++;
} else { } else {
wrong++; wrong++;
} }
}); });
const percentage = Math.round((correct / QUESTIONS.length) * 100); const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden'); document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden'); document.getElementById('result-section').classList.remove('hidden');

View File

@ -0,0 +1,401 @@
<!-- no-design-system -->
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Наймандар, керейіттер және жалайырлар</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⚔️</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Наймандар, керейіттер және жалайырлар</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">45</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 45</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "Наймандар VIII ғасырдың ортасында қай өзендердің аралығында қалыптасты?", options: ["Еділ мен Жайық", "Ертіс пен Орхон", "Іле мен Шу", "Сырдария мен Әмудария"], correct: 1 },
{ q: "840 жылы қандай мемлекет құлады?", options: ["Ляо империясы", "Керейіт мемлекеті", "Ұйғыр қағанаты", "Найман хандығы"], correct: 2 },
{ q: "Ұйғыр қағанаты құлағаннан кейін қандай үдеріс басталды?", options: ["Отырықшы мемлекеттердің жойылуы", "Орталық Азиядағы көшпелі тайпалық одақтардың қалыптасуы", "Қытайдың Орталық Азияны жаулап алуы", "Қазақ хандығының құрылуы"], correct: 1 },
{ q: "Наймандар мен керейіттер билеушілері XI ғасырдың басында қандай дінді қабылдады?", options: ["Буддизм", "Ислам", "Несториандық христиандық", "Манихейлік"], correct: 2 },
{ q: "Наймандар мен керейіттер қай мемлекетпен күшті қарсылас болды?", options: ["Алтын Ордамен", "Ляо мемлекетімен", "Қарахан мемлекетімен", "Қытай империясымен"], correct: 1 },
{ q: "Наймандар мен керейіттер Ляо империясының құрамына қай ғасырдың соңында енді?", options: ["X ғасырдың соңында", "XI ғасырдың басында", "XI ғасырдың соңында", "XII ғасырдың ортасында"], correct: 2 },
{ q: "Ляо империясы қай жылы құлады?", options: ["840 жылы", "1125 жылы", "1201 жылы", "1204 жылы"], correct: 1 },
{ q: "Ляо империясы құлағаннан кейін наймандар мен керейіттер қандай мүмкіндік алды?", options: ["Қытайды жаулап алды", "Тәуелсіздігін алды", "Монғолдарға қосылды", "Ислам дінін қабылдады"], correct: 1 },
{ q: "Найман мемлекеті қай аумақтарды иеленді?", options: ["Батыс Монғолия мен Шығыс Қазақстан", "Оңтүстік Қазақстан мен Орта Азия", "Батыс Қазақстан мен Еділ бойы", "Жетісу мен Сырдария бойы"], correct: 0 },
{ q: "Найман мемлекеті гүлденген кезеңіне қай ғасырдың екінші жартысында жетті?", options: ["X ғасырда", "XI ғасырда", "XII ғасырда", "XIII ғасырда"], correct: 2 },
{ q: "Наймандарда қандай шаруашылық пен мәдени салалар дамыды?", options: ["Тек мал шаруашылығы", "Қала мәдениеті мен егіншілік", "Теңіз саудасы мен кеме жасау", "Тек қолөнер"], correct: 1 },
{ q: "Наймандардың барлық сегіз тайпасы қандай кезеңде біртұтас мемлекетке бірікті?", options: ["VIII ғасырда", "IX ғасырда", "XII ғасырда", "XIV ғасырда"], correct: 2 },
{ q: "Найман мемлекетінің ордасы қай қалада орналасты?", options: ["Битөбе", "Баласағұн", "Балықты", "Отырар"], correct: 2 },
{ q: "Найман мемлекетінің ордасы қай өзеннің жағасында орналасты?", options: ["Ертіс", "Орхон", "Іле", "Енисей"], correct: 1 },
{ q: "Наймандардың батыстағы көршісі кімдер болды?", options: ["Керейіттер", "Қыпшақтар", "Енисей қырғыздары", "Жалайырлар"], correct: 1 },
{ q: "Наймандардың солтүстіктегі көршісі кімдер болды?", options: ["Қыпшақтар", "Керейіттер", "Енисей қырғыздары", "Қидандар"], correct: 2 },
{ q: "Наймандардың шығыстағы көршісі кімдер болды?", options: ["Керейіттер", "Қыпшақтар", "Жалайырлар", "Қидандар"], correct: 0 },
{ q: "Наймандар кімдермен Орталық Азиядағы көшпелілерге билік жүргізу үшін бақталасты?", options: ["Қыпшақтармен", "Керейіттермен", "Қырғыздармен", "Қидандармен"], correct: 1 },
{ q: "Наймандар Керейіт мемлекетінде қандай әрекет жасай алды?", options: ["Мемлекетті толық жойды", "Өз адамдарын таққа бірнеше рет отырғызды", "Астанасын басып алды", "Мемлекетпен сауда қатынасын тоқтатты"], correct: 1 },
{ q: "XII ғасырдың соңы – XIII ғасырдың басында Найман хандығында қандай өзгеріс болды?", options: ["Мемлекет күшейді", "Екі бөлікке ыдырады", "Ляо құрамына қайта кірді", "Керейіттерге қосылды"], correct: 1 },
{ q: "Наймандар монғолдардың күшеюін тоқтату мақсатында қай жылы құрылтай ұйымдастырды?", options: ["1125 жылы", "1180 жылы", "1201 жылы", "1204 жылы"], correct: 2 },
{ q: "1201 жылғы наймандар ұйымдастырған құрылтайға кімдер қатысты?", options: ["Тек наймандар", "Түркі тілдес тайпа өкілдері", "Қытай елшілері", "Енисей қырғыздары ғана"], correct: 1 },
{ q: "1201 жылы наймандар мен олардың одақтастары кімдерден жеңілді?", options: ["Қыпшақтардан", "Қидандардан", "Монғолдардан", "Керейіттерден"], correct: 2 },
{ q: "Монғолдар наймандарды толықтай қай жылы жеңді?", options: ["1201 жылы", "1202 жылы", "1203 жылы", "1204 жылы"], correct: 3 },
{ q: "Найманның соңғы билеушісінің баласы кім?", options: ["Тоғрұл", "Мұқылай", "Күшлік", "Жамұқа"], correct: 2 },
{ q: "Күшлік жеңілістен кейін қалған әскерін қай өңірге алып кетті?", options: ["Батыс Қазақстанға", "Жетісуға", "Еділ бойына", "Хуанхэ бойына"], correct: 1 },
{ q: "XII ғасырда Керейіт мемлекеті солтүстігінде қай өзеннен оңтүстігінде қай өзенге дейінгі жерді иеленді?", options: ["Ертістен Сырдарияға дейін", "Орхоннан Хуанхэге дейін", "Енисейден Ілеге дейін", "Іледен Әмударияға дейін"], correct: 1 },
{ q: "Керейіт мемлекетінің бас ордасы қай жерде орналасты?", options: ["Балықты", "Битөбе", "Баласағұн", "Отырар"], correct: 1 },
{ q: "XII ғасырдың екінші жартысында Керейіт мемлекетін кім басқарды?", options: ["Күшлік хан", "Жамұқа", "Тоғрұл хан", "Мұқылай"], correct: 2 },
{ q: "Тоғрұл хан билігі кезінде Керейіт мемлекетінде қандай өзгеріс болды?", options: ["Мемлекет әлсіреді", "Мемлекет аумағы өсіп, нығайды", "Мемлекет Ляоға қосылды", "Мемлекет екіге бөлінді"], correct: 1 },
{ q: "80-жылдардың басында Тоғрұл хан кімге қолдау көрсетті?", options: ["Күшлікке", "Жамұқаға", "Темучинге", "Мұқылайға"], correct: 2 },
{ q: "Тоғрұл хан Темучинге қолдау көрсету арқылы қандай мақсат көздеді?", options: ["Қытайды жаулап алуды", "Монғолдар арасындағы ықпалын нығайтуды", "Наймандардан қорғануды", "Жетісуға қоныс аударуды"], correct: 1 },
{ q: "Біраз уақыт Тоғрұл хан қай одақтың жетекшісі болды?", options: ["Найман-қыпшақ одағының", "Керейіт-жалайыр одағының", "Керейіт-найман одағының", "Монғол-қытай одағының"], correct: 2 },
{ q: "Керейіт мемлекеті монғолдардан қай жылы жеңілді?", options: ["1125 жылы", "1201 жылы", "1203 жылы", "1204 жылы"], correct: 2 },
{ q: "Найман мен Керейіт мемлекеттерінің саяси құрылымына тән белгі қайсы?", options: ["Екеуінде де хан сайлау арқылы билік етті", "Екеуін де мұрагерлік жолмен хан басқарды", "Екеуінде де билік тек діни көсемдердің қолында болды", "Екеуінде де республика басқару жүйесі болды"], correct: 1 },
{ q: "Найман мен Керейіт мемлекеттерінде ресми құжаттар немен бекітілді?", options: ["Таңбамен", "Мөрмен", "Қылышпен", "Елшілік белгісімен"], correct: 1 },
{ q: "Ақсүйектердің қызметі қандай жолмен берілді?", options: ["Сайлау арқылы", "Соғыс нәтижесінде", "Мұрагерлік жолмен", "Құрылтай шешімімен ғана"], correct: 2 },
{ q: "Мемлекеттің бүкіл халқы қандай әскери-әкімшілік жүйе бойынша бөлінді?", options: ["Тайпа, ру, ауыл", "Мыңдық, жүздік, ондық", "Ұлыс, хандық, аймақ", "Облыс, аудан, ауыл"], correct: 1 },
{ q: "XIII ғасырдың басында монғолдардың қысымымен найман мен керейіттер қай аумақтарға қоныс аударды?", options: ["Батыс Қазақстан мен Еділ бойына", "Шығыс Қазақстан мен Жетісуға", "Орталық Қазақстан мен Сарыарқаға", "Оңтүстік Қазақстан мен Арал маңына"], correct: 1 },
{ q: "Найман мен керейіттердің қоныс аударуының тарихи маңызы қандай болды?", options: ["Жергілікті халықтың мәдени және этникалық дамуына ықпал етті", "Қытай мәдениетін толық жойды", "Қазақстандағы қалаларды жойды", "Қазақ хандығын бірден құрды"], correct: 0 },
{ q: "Жалайырлар туралы мәлімет негізінен қай деректерде кездеседі?", options: ["Араб жылнамаларында", "Парсы жазбаларында", "Монғол жылнамаларында", "Қытай шежірелерінде"], correct: 2 },
{ q: "VI–VII ғасырларда жалайырлар қай мемлекеттің құрамына енді?", options: ["Ұйғыр қағанатының", "Түрік қағанатының", "Ляо империясының", "Найман мемлекетінің"], correct: 1 },
{ q: "Өзін гурхан жариялап, қысқа мерзімге жалайырлар мемлекетін құрған тұлға кім?", options: ["Тоғрұл", "Күшлік", "Жамұқа", "Мұқылай"], correct: 2 },
{ q: "Шыңғысхан жалайырларға қатысты қандай әрекет жасады?", options: ["Оларды Керейіттерге қосты", "Оларды талқандап, өзіне бағындырды", "Оларға тәуелсіздік берді", "Оларды Жетісудан қуып шығарды"], correct: 1 },
{ q: "«Жамиғ ат-тауарих» еңбегінің авторы әрі жалайыр тайпасынан шыққан тарихшы кім?", options: ["Мұқылай", "Жамұқа", "Қадырғали Жалаири", "Тоғрұл хан"], correct: 2 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>

401
oghyz-memleketi.html Normal file
View File

@ -0,0 +1,401 @@
<!-- no-design-system -->
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Оғыз мемлекеті</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🐍</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Оғыз мемлекеті</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">45</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 45</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "Батыс Түрік қағанатының орнына қазіргі Қазақстан аумағында қандай мемлекеттер қалыптасты?", options: ["Қарахан, Қыпшақ, Найман", "Оғыз, Қимақ, Түргеш", "Хазар, Қарлұқ, Қарахан", "Керей, Жалайыр, Найман"], correct: 1 },
{ q: "Оғыз мемлекеті қазіргі Қазақстанның қай бөлігінде қалыптасты?", options: ["Жетісуда", "Солтүстік-шығыста", "Батыс Қазақстанда", "Оңтүстік-шығыста"], correct: 2 },
{ q: "Қимақ қағанаты Қазақстанның қай аймақтарында қалыптасты?", options: ["Батыс және Оңтүстік Қазақстанда", "Солтүстік-шығыс және Орталық Қазақстанда", "Жетісу мен Маңғыстауда", "Оңтүстік Қазақстанда"], correct: 1 },
{ q: "Түргеш мемлекеті қай аймақта қалыптасты?", options: ["Жетісуда", "Батыс Қазақстанда", "Солтүстік Қазақстанда", "Маңғыстауда"], correct: 0 },
{ q: "Оғыздар туралы араб тіліндегі деректер қай кезеңге жатады?", options: ["VII–VIII ғасырлар", "VIII–IX ғасырлар", "IX–X ғасырлардың басы", "XI–XII ғасырлар"], correct: 2 },
{ q: "Оғыздардың мемлекет болғандығы туралы жазған авторларды көрсетіңіз.", options: ["Әл-Якуби мен әл-Факих", "Әл-Бируни мен Ибн Сина", "Рашид ад-Дин мен Жүсіп Баласағұни", "Әл-Фараби мен Махмұд Қашғари"], correct: 0 },
{ q: "Оғыздардың тайпалық құрамы туралы мәліметтер қай ғалымның еңбектерінде кездеседі?", options: ["Әл-Якуби", "Махмұд Қашғари", "Әл-Факих", "Ибн Сина"], correct: 1 },
{ q: "Махмұд Қашғари деректерінде оғыздар бастапқы кезде неше тайпаға бірікті?", options: ["12", "16", "20", "24"], correct: 3 },
{ q: "Оғыздар қандай екі топқа бөлінді?", options: ["Ақ орда және Көк орда", "Боз оқ және Үш оқ", "Оң қанат және Сол қанат", "Үш жүз және Ұлы жүз"], correct: 1 },
{ q: "Оғыз қоғамында қай топ ерекше артықшылыққа ие болды?", options: ["Үш оқтар", "Қыпшақтар", "Боз оқтар", "Қарлұқтар"], correct: 2 },
{ q: "Орыс жылнамаларында оғыздар қалай аталған?", options: ["Торк", "Теле", "Татаб", "Түрік"], correct: 0 },
{ q: "Орыс жылнамаларындағы «торк» атауы қандай тайпамен байланысты?", options: ["Қимақтармен", "Оғыздармен", "Түргештермен", "Қарлұқтармен"], correct: 1 },
{ q: "Оғыздардың тарихындағы бірқатар оқиғалар қай шығармада баяндалады?", options: ["«Кодекс Куманикус»", "«Құтадғу білік»", "«Оғызнама»", "«Диуани хикмет»"], correct: 2 },
{ q: "Оғыздардың құрамына қандай тайпалар кірді?", options: ["Тек түркі тілдес тайпалар", "Тек үндіеуропалық тайпалар", "Түркі тілдес, үндіеуропалық және финн-угор тектес тайпалар", "Тек финн-угор тайпалары"], correct: 2 },
{ q: "Деректерге сәйкес оғыз тайпалары алғаш қай жерде қалыптасты?", options: ["Сырдария бойында", "Жетісу аумағында", "Еділ бойында", "Солтүстік Кавказда"], correct: 1 },
{ q: "VIII ғасырдың екінші жартысында оғыздар кімдермен күрес нәтижесінде Жетісудан көшті?", options: ["Қыпшақтармен", "Печенегтермен", "Қарлұқтармен", "Хазарлармен"], correct: 2 },
{ q: "Оғыздар Жетісудан көшкеннен кейін қай аумаққа қоныс аударды?", options: ["Ертіс бойына", "Сырдария бойына", "Есіл бойына", "Жайықтың жоғарғы ағысына"], correct: 1 },
{ q: "Оғыздар Сырдария бойында қандай аумақтарды басып алды?", options: ["Сырдарияның төменгі ағысы мен Арал маңы далаларын", "Ертістің жоғарғы ағысы мен Алтайды", "Іле аңғары мен Тарбағатайды", "Шу мен Талас аңғарларын"], correct: 0 },
{ q: "Оғыз мемлекетінің орталығы болған қала:", options: ["Сығанақ", "Сауран", "Янгикент", "Тараз"], correct: 2 },
{ q: "Янгикент қаласы қай өзеннің бойында орналасты?", options: ["Ертіс", "Іле", "Сырдария", "Жайық"], correct: 2 },
{ q: "Мәтінде «Ит жылы» деп көрсетілген жыл:", options: ["726 жыл", "736 жыл", "746 жыл", "756 жыл"], correct: 2 },
{ q: "746 жылы Жетісуға қай тайпалар қоныс аударды?", options: ["Қыпшақтар", "Қарлұқтар", "Оғыздар", "Печенегтер"], correct: 1 },
{ q: "IX ғасырдың соңында оғыздар кімдермен одақтасты?", options: ["Киев Русімен", "Хазарлармен", "Қыпшақтармен", "Қарлұқтармен"], correct: 1 },
{ q: "Оғыздар IX ғасырдың соңында хазарлармен бірігіп кімдерге қарсы күресті?", options: ["Печенегтерге", "Қыпшақтарға", "Қарлұқтарға", "Түргештерге"], correct: 0 },
{ q: "Печенегтермен болған ұзақ күрес қандай нәтижеге ықпал етті?", options: ["Оғыздардың Жетісуға қайта оралуына", "Оғыз мемлекетінің құрылуына", "Қимақ қағанатының құрылуына", "Хазар қағанатының құрылуына"], correct: 1 },
{ q: "965 жылы оғыздар қай мемлекетпен одақтасып Хазар қағанатын талқандады?", options: ["Қимақ қағанатымен", "Киев Русімен", "Қарахан мемлекетімен", "Еділ Бұлғариясымен"], correct: 1 },
{ q: "Оғыздардың Хазар қағанатына қарсы күрестегі негізгі мақсаттарының бірі:", options: ["Жетісуды басып алу", "Қара теңіз жағалауындағы құнарлы жайылымдарды иемдену", "Қытайға жорық жасау", "Сырдарияның жоғарғы ағысын басып алу"], correct: 1 },
{ q: "Оғыздар Хазарларға қарсы күресте қандай сауда жолына бақылау орнатуды көздеді?", options: ["Іле бойындағы сауда жолына", "Ертіс бойындағы сауда жолына", "Еділ бойымен өтетін сауда жолына", "Ұлы Жібек жолының Жетісу бағытына"], correct: 2 },
{ q: "985 жылы оғыз билеушісі кіммен одақтасты?", options: ["Киев князы Владимирмен", "Хазар қағанымен", "Қыпшақ хандығымен", "Қарлұқ жабғуымен"], correct: 0 },
{ q: "985 жылы оғыздар кімдерді жеңді?", options: ["Печенегтерді", "Хазарларды", "Еділ Бұлғариясын", "Қыпшақтарды"], correct: 2 },
{ q: "Еділ Бұлғариясын жеңу Оғыз мемлекетіне қандай әсер етті?", options: ["Саяси жағынан әлсіреді", "Саяси жағынан күшейді", "Мемлекет құлады", "Жетісуға көшті"], correct: 1 },
{ q: "Белсенді сыртқы саясат нәтижесінде оғыздар оңтүстікте қай аймақпен шектесті?", options: ["Мауараннахрмен", "Жетісумен", "Сібірмен", "Хорасанмен"], correct: 0 },
{ q: "Оғыздардың батыстағы шекарасы қай аймаққа дейін жетті?", options: ["Қырымға", "Кавказ аймағына", "Балқанға", "Еуропаның орталығына"], correct: 1 },
{ q: "Белсенді сыртқы саясат пен ұзақ соғыстардың негізгі салдарының бірі:", options: ["Салықтың жойылуы", "Салықтың жыл сайын өсуі", "Мемлекеттің байып кетуі", "Көшпелі өмір салтының тоқтауы"], correct: 1 },
{ q: "Х–ХІ ғасырлар аралығында оғыз тайпалары неге қарсы көтеріліс жасады?", options: ["Дінге қарсы", "Сыртқы жауға қарсы", "Салық жинауға қарсы", "Саудаға қарсы"], correct: 2 },
{ q: "Оғыздардағы дағдарысты өз мақсаттарына пайдаланғандар:", options: ["Қарлұқтар", "Салжұқ көсемдері", "Хазарлар", "Печенегтер"], correct: 1 },
{ q: "Салжұқ көсемдері кімдерге қарсы көтеріліске басшылық етті?", options: ["Оғыз билеушілеріне", "Қыпшақтарға", "Киев Русіне", "Хазарларға"], correct: 0 },
{ q: "Шахмәлiк жабғу тұсында Оғыз мемлекетінде қандай жағдай орын алды?", options: ["Мемлекет қайтадан күшейді", "Мемлекет бірден құлады", "Жетісуға көшіп кетті", "Хазарларға бағынышты болды"], correct: 0 },
{ q: "Шахмәлiк жабғу тұсында Оғыздар қай жылы Хорезмді басып алды?", options: ["985 жылы", "1001 жылы", "1041 жылы", "1043 жылы"], correct: 2 },
{ q: "Шахмәлiк екі жылдан кейін кімдердің қолына тұтқынға түсті?", options: ["Қыпшақтардың", "Салжұқтардың", "Хазарлардың", "Печенегтердің"], correct: 1 },
{ q: "Шахмәлiк жабғудың тарихи рөлі қандай?", options: ["Оғыздардың алғашқы билеушісі болды", "Оғыздардың соңғы билеушісі болды", "Қимақтардың билеушісі болды", "Хазарлардың билеушісі болды"], correct: 1 },
{ q: "Оғыз мемлекетін әлсіреткен негізгі факторларды анықтаңыз.", options: ["Қарлұқтармен одақ және сауданың дамуы", "Салжұқтармен ұзақ соғыстар және ауыр салыққа қарсы көтерілістер", "Егіншіліктің дамуы және қолөнердің өсуі", "Исламның таралуы және қалалардың көбеюі"], correct: 1 },
{ q: "Әлсіреген Оғыз мемлекетін түпкілікті құлатқан күш:", options: ["Қарлұқ тайпалары", "Салжұқтар", "Қыпшақ тайпаларының көсемдері", "Хазарлар"], correct: 2 },
{ q: "Оғыздардың негізгі шаруашылығы қандай болды?", options: ["Егіншілік", "Қолөнер", "Көшпелі мал шаруашылығы", "Балық аулау"], correct: 2 },
{ q: "Оғыздардың X–XI ғасырлардағы қалалары қатарын көрсетіңіз.", options: ["Тараз, Баласағұн, Суяб", "Жент, Сауран, Сығанақ", "Отырар, Испиджаб, Талғар", "Сарайшық, Түркістан, Баласағұн"], correct: 1 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>

391
qanly-uysin-sarmattar.html Normal file
View File

@ -0,0 +1,391 @@
<!-- no-design-system -->
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Қаңлы, Үйсін және Сарматтар</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏛️</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Қаңлы, Үйсін және Сарматтар</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">35</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 35</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "Қаңлы мемлекеті қай ғасырда Сырдарияның орта ағысында күшейді?", options: ["Б.з.б. IV ғасырда", "Б.з.б. III ғасырда", "Б.з.б. II ғасырда", "Б.з.б. I ғасырда"], correct: 2 },
{ q: "Қаңлылар алғашында қай мемлекеттерге тәуелді болды?", options: ["Үйсіндер мен Қытайға", "Юэчжилер мен ғұндарға", "Сарматтар мен сақтарға", "Массагеттер мен аландарға"], correct: 1 },
{ q: "Қаңлы мемлекетінің билігі қай аймақтарға дейін таралды?", options: ["Шығыс Қазақстан мен Алтайға", "Солтүстік Қазақстан мен Сібірге", "Батыс Қазақстан мен Каспийдің солтүстік жағалауларына", "Оңтүстік Қазақстан мен Қытайдың ішкі бөлігіне"], correct: 2 },
{ q: "Қаңлылар Батыс Қазақстанда билік жүргізген кезде оларға кімдер тәуелді болды?", options: ["Сақтар мен үйсіндер", "Массагеттер, кейін сармат-алан тайпалары", "Ғұндар мен юэчжилер", "Қытайлар мен жужандар"], correct: 1 },
{ q: "Қаңлы мемлекетінің құрамына біраз уақыт кірген аймақтарды көрсетіңіз.", options: ["Шаш, Ферғана, Хорезм", "Жетісу, Тарбағатай, Алтай", "Моңғолия, Шығыс Түркістан, Қытай", "Еділ бойы, Қара теңіз, Кавказ"], correct: 0 },
{ q: "Қаңлы мемлекетінің астанасы болған қала:", options: ["Чигу", "Битянь", "Суяб", "Баласағұн"], correct: 1 },
{ q: "Қаңлылардың негізгі халқы қандай шаруашылықпен айналысты?", options: ["Тек отырықшы егіншілікпен", "Тек қолөнермен", "Көшпелі шаруашылықпен", "Теңіз саудасымен"], correct: 2 },
{ q: "Қаңлылар шұраттарда қандай шаруашылықпен айналысты?", options: ["Балық аулаумен", "Егіншілікпен", "Аңшылықпен", "Тау-кен өндірісімен"], correct: 1 },
{ q: "Қаңлылардың сарай үлгісіндегі құрылыстары зерттелген орындардың бірі:", options: ["Ақтөбе қалашығы", "Берел қорғаны", "Бесшатыр қорғаны", "Есік қалашығы"], correct: 0 },
{ q: "Ақтөбе қалашығы қай өзеннің оң жағалауында орналасқан?", options: ["Іле", "Шу", "Сырдария", "Талас"], correct: 2 },
{ q: "Б.з.б. 101 жылы Қытай Даваниді жаулап алған кезде Қаңлы мемлекеті кімдердің жағына шықты?", options: ["Қытайлардың", "Ғұндардың", "Ферғаналықтардың", "Үйсіндердің"], correct: 2 },
{ q: "Б.з.б. 47–46 жылдары қаңлылар кімге қарсы күресте солтүстік ғұн билеушісіне қолдау көрсетті?", options: ["Қытайларға", "Үйсіндерге", "Сарматтарға", "Юэчжилерге"], correct: 1 },
{ q: "Кейін қаңлылар ғұндарға қарсы кіммен одақ жасасты?", options: ["Үйсіндермен", "Сарматтармен", "Қытаймен", "Юэчжилермен"], correct: 2 },
{ q: "Қаңлы мемлекеті бірнеше иелікке қай ғасырларда бөлінді?", options: ["Б.з.б. IV–III ғасырларда", "Б.з.б. II–I ғасырларда", "I–II ғасырларда", "IV–V ғасырларда"], correct: 2 },
{ q: "V ғасырда Қаңлы мемлекеті қай елдің императорлық сарайына елшілік жіберді?", options: ["Үндістан", "Қытай", "Парсы", "Рим"], correct: 1 },
{ q: "Үйсін мемлекеті негізінен қай аумақта құрылды?", options: ["Батыс Қазақстан мен Каспий маңында", "Жетісу, Тарбағатай және Тянь-Шань аумағында", "Сырдарияның төменгі ағысында", "Еділ мен Жайық аралығында"], correct: 1 },
{ q: "Үйсіндер кімдердің ұрпақтары деп көрсетілген?", options: ["Сақ тиграхаудалардың", "Массагеттердің", "Сарматтардың", "Ғұндардың"], correct: 0 },
{ q: "Үйсіндердің шаруашылығының негізгі сипаты:", options: ["Толық отырықшы егіншілік", "Жартылай көшпелі шаруашылық", "Теңіз саудасы", "Тек аңшылық"], correct: 1 },
{ q: "Үйсіндердегі жоғары билеушінің атауы:", options: ["Шаньюй", "Гуньмо (Күнби)", "Тулы", "Уәзір"], correct: 1 },
{ q: "Үйсіндердің билеушісі Күнбидің сарайы орналасқан қала:", options: ["Битянь", "Чигу", "Даван", "Шаш"], correct: 1 },
{ q: "Чигу қаласының мағынасы:", options: ["Алтын қала", "Қызыл Аңғар", "Үлкен қала", "Көк қала"], correct: 1 },
{ q: "Үйсін мемлекеті қандай бөліктерге бөлінді?", options: ["Сол жақ, оң жақ және орталық", "Солтүстік, оңтүстік және батыс", "Шығыс, батыс және солтүстік", "Орталық, солтүстік және оңтүстік"], correct: 0 },
{ q: "Күнбиден кейінгі жоғары лауазымды тұлға:", options: ["Шаньюй", "Тулы (дулы)", "Қаған", "Тархан"], correct: 1 },
{ q: "Үйсіндерде шенеуніктерден, тексерушілерден және хатшылардан тұратын қандай құрылым болды?", options: ["Әскери кеңес", "Төрешілік аппараты", "Сауда кеңесі", "Халық жиналысы"], correct: 1 },
{ q: "Үйсіндер туралы негізгі ақпарат қай деректерден белгілі?", options: ["Рим деректерінен", "Парсы деректерінен", "Қытай деректерінен", "Үнді деректерінен"], correct: 2 },
{ q: "Үйсіндердің батыс шегі қай өзендердің бойымен өтті?", options: ["Іле мен Ертіс", "Шу мен Талас", "Сырдария мен Әмудария", "Еділ мен Жайық"], correct: 1 },
{ q: "Б.з.б. II ғасырда үйсіндер кімдермен ғұндарға қарсы одақтасты?", options: ["Сарматтармен", "Қаңлылармен", "Қытайлармен", "Массагеттермен"], correct: 2 },
{ q: "Б.з.б. I ғасырда Үйсін мемлекеті қандай екі иелікке бөлінді?", options: ["Сол және оң қанатқа", "Үлкен күнби және Кіші күнби иеліктеріне", "Шығыс және Батыс иеліктерге", "Орталық және Батыс иеліктерге"], correct: 1 },
{ q: "Б.з. II ғасырда үйсіндер қандай жағдайға жетті?", options: ["Қытайға толық бағынды", "Қаңлы мемлекетіне қосылды", "Қытайдан толық құтылды", "Сарматтарға тәуелді болды"], correct: 2 },
{ q: "IV ғасырда үйсіндер кімдердің қысымымен Тянь-Шань тауларына қоныс аударды?", options: ["Ғұндардың", "Қытайлардың", "Жужандардың", "Сарматтардың"], correct: 2 },
{ q: "Сарматтар Геродот деректерінде қалай аталды?", options: ["Скифтер", "Савроматтар", "Массагеттер", "Юэчжилер"], correct: 1 },
{ q: "Сарматтар қай аймақты мекендеді?", options: ["Жетісу мен Тянь-Шаньды", "Батыс Қазақстан, Еділ мен Жайық аралығын", "Сырдария мен Әмудария аралығын", "Алтай мен Тарбағатайды"], correct: 1 },
{ q: "Б.з.б. III ғасырда сарматтарды Ұлы Даланың батыс бөлігінен ығыстырғандар:", options: ["Ғұндар", "Қытайлар", "Дах-массагеттер", "Үйсіндер"], correct: 2 },
{ q: "Сарматтарға тән мәдени ерекшеліктердің бірі:", options: ["Пирамидалар тұрғызу", "Ақинақ жасау және «аң» стилін қолдану", "Жазу-сызудың болмауы", "Теңіз кемелерін жасау"], correct: 1 },
{ q: "Сарматтардың тарихи маңызы неде?", options: ["Қытай мен Үндістанды байланыстырды", "Еуропа мен Қытайды тікелей байланыстырды", "Орталық Азиядағы сақтар мен Қара теңіз маңындағы скифтерді байланыстырды", "Қаңлы мен Үйсін мемлекеттерін біріктірді"], correct: 2 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>

401
qarahan-memleketi.html Normal file
View File

@ -0,0 +1,401 @@
<!-- no-design-system -->
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Қарахан мемлекеті</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🕌</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Қарахан мемлекеті</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">45</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 45</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "Қарахан мемлекеті туралы деректер көп кездесетін авторлар:", options: ["Қытай және үнді авторлары", "Араб және парсы авторлары", "Грек және рим авторлары", "Орыс және моңғол авторлары"], correct: 1 },
{ q: "Қарахан әулетінің шығу тегі қай тайпалармен байланысты?", options: ["Қыпшақтармен", "Наймандармен", "Қашғарияда өмір сүрген қарлұқтармен", "Керейлермен"], correct: 2 },
{ q: "940 жылы Қашғарияның қарлұқ тайпалары қай қаланы басып алды?", options: ["Бұхараны", "Самарқандты", "Таразды", "Баласағұнды"], correct: 3 },
{ q: "940 жылы Баласағұнды басып алғаннан кейін жаңа әулеттің негізін қалаған билеуші:", options: ["Сатұқ Боғра хан", "Мұса қаған", "Күшлік хан", "Мұхаммед Хорезм шахы"], correct: 0 },
{ q: "Сатұқ Боғра хан Қарахан мемлекетін ресми түрде қай жылы құрды?", options: ["940 жылы", "942 жылы", "960 жылы", "999 жылы"], correct: 1 },
{ q: "Қарахан мемлекетінің атауы болжам бойынша кімнің есімімен байланысты?", options: ["Сатұқ Боғра ханның", "Мұса қағанның", "Қараханның", "Күшліктің"], correct: 2 },
{ q: "999 жылы қарахандықтар қай мемлекетті талқандады?", options: ["Газнауилер мемлекетін", "Қыпшақ хандығын", "Қарақытай мемлекетін", "Самани мемлекетін"], correct: 3 },
{ q: "Қарахан мемлекеті мен Газнауилер арасындағы шекара болған өзен:", options: ["Сырдария", "Ертіс", "Әмудария", "Іле"], correct: 2 },
{ q: "Қарахан мемлекетінің батыстағы негізгі иелігі:", options: ["Қашғар", "Мауараннахр", "Алтай", "Моңғолия"], correct: 1 },
{ q: "Қарахан мемлекетінің шығыстағы иелігі:", options: ["Қашғар", "Бұхара", "Самарқанд", "Мауараннахр"], correct: 0 },
{ q: "Қарахан мемлекетінде билік қай екі тайпалық топтың ақсүйектері арасында бөлінді?", options: ["Қыпшақ пен керей", "Жікіл мен яғма", "Найман мен қоңырат", "Үйсін мен дулат"], correct: 1 },
{ q: "Қарахан мемлекетінде қалыптасқан билік жүйесі қалай аталды?", options: ["Абсолюттік монархия", "Әскери демократия", "Тең құқықты қосарлы жүйе", "Республикалық жүйе"], correct: 2 },
{ q: "Қарахан мемлекетінің шығыс бөлігінің қағаны қандай атақ иеленді?", options: ["Боғра Қара қаған", "Арслан Қара қаған", "Ханбалық қаған", "Тархан қаған"], correct: 1 },
{ q: "Шығыс бөліктің ордасы орналасқан қалалар:", options: ["Бұхара мен Самарқанд", "Тараз бен Испиджаб", "Қашғар мен Баласағұн", "Отырар мен Сауран"], correct: 2 },
{ q: "Қарахан мемлекетінің батыс бөлігінің қағаны қандай атаққа ие болды?", options: ["Арслан Қара қаған", "Боғра Қара қаған", "Ұлы қаған", "Шад қаған"], correct: 1 },
{ q: "Батыс бөліктің ордасы бастапқыда қай қалада орналасты?", options: ["Бұхарада", "Қашғарда", "Баласағұнда", "Таразда"], correct: 0 },
{ q: "Кейін Батыс Қарахан бөлігінің ордасы қай қалаға көшірілді?", options: ["Қашғарға", "Самарқандқа", "Баласағұнға", "Таразға"], correct: 1 },
{ q: "Қарахан мемлекетінің шығыс бөлігі қай тайпамен байланысты болды?", options: ["Яғма", "Қыпшақ", "Жікіл", "Қарлұқ"], correct: 2 },
{ q: "Қарахан мемлекетінің батыс бөлігі қай тайпамен байланысты болды?", options: ["Жікіл", "Яғма", "Қыпшақ", "Найман"], correct: 1 },
{ q: "Қарахан мемлекетінде қызметі үшін жер үлесін алған адамдар қалай аталды?", options: ["Вақфтар", "Иқтадарлар", "Тархандар", "Қағандар"], correct: 1 },
{ q: "Қызметі үшін берілген жер үлесі қалай аталды?", options: ["Мүлік", "Вақф", "Иқта", "Ұлыс"], correct: 2 },
{ q: "Қарахан мемлекетінде дінбасыларының жер меншігі қалай аталды?", options: ["Иқта", "Мүлік", "Вақф (уақып)", "Сойырғал"], correct: 2 },
{ q: "Қарахандықтардағы жекеменшік жер иелену түрі:", options: ["Вақф", "Мүлік", "Иқта", "Ұлыс"], correct: 1 },
{ q: "Иқталық жүйенің қалыптасуы қандай үдеріске ықпал етті?", options: ["Құл иеленушіліктің жойылуына", "Феодалдық қатынастардың дамуына", "Сауда қатынастарының тоқтауына", "Көшпелі шаруашылықтың жойылуына"], correct: 1 },
{ q: "Иқталық жүйе нәтижесінде қандай әлеуметтік топ қалыптасты?", options: ["Жаңа ақсүйек қауымы", "Құлдар қауымы", "Қолөнершілер қауымы", "Діни қызметкерлер қауымы"], correct: 0 },
{ q: "Иқталық жүйенің әлсіреткен саяси салдарының бірі:", options: ["Орталық биліктің күшеюі", "Қаған билігінің толық орнығуы", "Жеке жер иелерінің қағандарға бағынбауы", "Мемлекеттің аумағының кеңеюі"], correct: 2 },
{ q: "Қарахандықтарда исламның мемлекеттік дінге айналуымен байланысты билеуші:", options: ["Сатұқ Боғра хан", "Күшлік хан", "Мұса қаған", "Мұхаммед Хорезм шахы"], correct: 2 },
{ q: "Мұса қаған исламды мемлекеттік дін деп қай жылы жариялады?", options: ["940 жылы", "942 жылы", "960 жылы", "999 жылы"], correct: 2 },
{ q: "Мұса қаған исламды мемлекеттік дін деп қай қалада жариялады?", options: ["Баласағұнда", "Таразда", "Қашғарда", "Самарқандта"], correct: 1 },
{ q: "Қарахандықтардың ислам дінін қабылдауына себептердің бірі:", options: ["Қытаймен байланысты тоқтату", "Билікті нығайту және мұсылман елдерімен байланыстарды кеңейту", "Көшпелі өмір салтынан толық бас тарту", "Қыпшақтарды бағындыру"], correct: 1 },
{ q: "Қарахан мемлекетінің әлсіреуін пайдаланған көшпелі тайпалар:", options: ["Қыпшақтар", "Наймандар", "Қидандар (қарақытайлар)", "Керейлер"], correct: 2 },
{ q: "XII ғасырдың бас кезінен бастап Жетісу кімдердің шапқыншылығына ұшырады?", options: ["Қыпшақтардың", "Қарақытайлардың", "Саманилердің", "Газнауилердің"], correct: 1 },
{ q: "XI ғасырдың 30-жылдарының соңында Қарахан мемлекеті қандай бөліктерге бөлінді?", options: ["Солтүстік және Оңтүстік", "Орталық және Шығыс", "Мауараннахрдағы Батыс және Жетісу мен Қашғардағы Шығыс", "Жетісу және Сырдария"], correct: 2 },
{ q: "1210 жылы Шығыс Қарахан әулетін талқандаған:", options: ["Мұса қаған", "Күшлік хан", "Сатұқ Боғра хан", "Мұхаммед Хорезм шахы"], correct: 1 },
{ q: "1212 жылы Батыс Қарахан әулетінің соңғы өкілін тақтан тайдырған:", options: ["Найман ханы Күшлік", "Сатұқ Боғра хан", "Хорезм шахы Мұхаммед", "Мұса қаған"], correct: 2 },
{ q: "Қарахан мемлекетінің солтүстік шекарасы Қыпшақ хандығымен қай нысандардың бойымен өтті?", options: ["Арал және Каспий теңіздері", "Балқаш және Алакөл көлдері", "Іле және Ертіс өзендері", "Сырдария және Әмудария өзендері"], correct: 1 },
{ q: "Қарахан мемлекетінің Шығыс бөлігіндегі жоғары билеуші мен Батыс бөлігіндегі кіші билеушінің дұрыс сәйкестігін анықтаңыз.", options: ["Арслан Қара қаған — Батыс, Боғра Қара қаған — Шығыс", "Боғра Қара қаған — Шығыс, Арслан Қара қаған — Батыс", "Арслан Қара қаған — Шығыс, Боғра Қара қаған — Батыс", "Екеуі де Шығыс бөлікті басқарды"], correct: 2 },
{ q: "Қарахан мемлекетінде иқта иеленушілерінің негізгі құқықтарының бірі:", options: ["Мемлекет атынан соғыс жариялау", "Аймақ немесе қала тұрғындарынан салық жинау", "Қағанды сайлау", "Мемлекеттік дінді өзгерту"], correct: 1 },
{ q: "Жеке жер иелерінің күшеюі Қарахан мемлекетінде қандай жағдайға әкелді?", options: ["Орталық биліктің нығаюына", "Мемлекеттің аумағының ұлғаюына", "Өзара қырқыс пен саяси тұрақсыздыққа", "Ислам дінінің жойылуына"], correct: 2 },
{ q: "Кейбір жеке жер иелерінің тәуелсіздікке ұмтылғанын көрсететін әрекет:", options: ["Өз теңгелерін шығарып, дипломатиялық байланыстар жүргізуі", "Исламды мемлекеттік дін деп жариялауы", "Қарақытайларға қарсы көтеріліс бастауы", "Баласағұнды астана етуі"], correct: 0 },
{ q: "Төмендегі оқиғалардың дұрыс хронологиялық ретін анықтаңыз:\n\n1. Мұса исламды мемлекеттік дін деп жариялады.\n2. Қарахандықтар Самани мемлекетін талқандады.\n3. Баласағұнды қарлұқтар басып алды.\n4. Шығыс Қарахан әулеті талқандалды.", options: ["3 → 1 → 2 → 4", "1 → 3 → 2 → 4", "3 → 2 → 1 → 4", "2 → 3 → 1 → 4"], correct: 0 },
{ q: "Қарақытайлар Қарахан билеушілерін өздеріне тәуелді еткеннен кейін қандай саясат ұстанды?", options: ["Қарахан мемлекетін толығымен жойды", "Жергілікті дін мен мәдениетке тыйым салды", "Тек салық алумен шектеліп, жергілікті мемлекеттік құрылымды сақтады", "Барлық халықты көшіріп жіберді"], correct: 2 },
{ q: "Қарақытайлардың Қарахан мемлекетіне қатысты саясатының ерекшелігі:", options: ["Мұрагерлік қаған билігін сақтауы", "Исламды мемлекеттік дін ретінде жоюы", "Қарахан әулетін толықтай биліктен кетіруі", "Барлық қалаларды қиратуы"], correct: 0 },
{ q: "Екі Қарахан қағанаты арасындағы шекара қай өзен бойымен өтті?", options: ["Ертіс", "Іле", "Сырдария", "Әмудария"], correct: 2 },
{ q: "Қарахан мемлекетінің саяси құлдырауын білдіретін оқиғалар дұрыс көрсетілген қатарды анықтаңыз.", options: ["Саманилердің күшеюі → Қыпшақтардың шапқыншылығы", "Қарақытай үстемдігі → Шығыс және Батыс әулеттерінің жойылуы", "Исламның таралуы → Баласағұнның алынуы", "Иқталық жүйенің қалыптасуы → мемлекеттің күшеюі"], correct: 1 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>

401
qaraqytaylar-memleketi.html Normal file
View File

@ -0,0 +1,401 @@
<!-- no-design-system -->
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Қарақытайлар мемлекеті</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏹</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Қарақытайлар мемлекеті</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">45</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 45</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "Қидандар қай мемлекеттің құлауынан кейін Орталық Азияның шығыс бөлігіндегі билікті басып алды?", options: ["Қарахан мемлекеті", "Ұйғыр қағанаты", "Түрік қағанаты", "Найман мемлекеті"], correct: 1 },
{ q: "Қидандар 907–1125 жылдары құрған мемлекет қалай аталды?", options: ["Қарақытай", "Ляо", "Қарахан", "Хорезмшах"], correct: 1 },
{ q: "Қидандар жазба деректерде қандай тайпалар ретінде сипатталды?", options: ["Түркі тілдес", "Иран тілдес", "Монғол тілдес", "Славян тілдес"], correct: 2 },
{ q: "Ляо мемлекеті қай жылы талқандалды?", options: ["907 жылы", "1125 жылы", "1128 жылы", "1141 жылы"], correct: 1 },
{ q: "1125 жылы Ляо мемлекетін кімдер талқандады?", options: ["Наймандар мен керейлер", "Хорезмшахтар мен қарахандар", "Қытайдың біріккен күштері мен олардың одақтастары", "Салжұқтар мен моңғолдар"], correct: 2 },
{ q: "Қидандардың батысқа қарай жылжуына кім басшылық етті?", options: ["Мұхаммед Хорезмшах", "Күшлік хан", "Елюй Даши", "Шыңғыс хан"], correct: 2 },
{ q: "Қидандар батысқа жылжып, қай өңірге енді?", options: ["Сырдарияның төменгі ағысына", "Жетісудың солтүстік-шығысына", "Маңғыстауға", "Еділ бойына"], correct: 1 },
{ q: "Жергілікті түркі халқымен араласқан қидандар қандай атаумен белгілі болды?", options: ["Қыпшақтар", "Қарахандар", "Қарақытайлар", "Наймандар"], correct: 2 },
{ q: "1128 жылы Баласағұн билеушісі қидандарды не үшін шақырды?", options: ["Қытайға қарсы соғысу үшін", "Бағынбаған тайпаларға қарсы одақтас ретінде", "Сауда келісімін жасау үшін", "Хорезмшахтарға қарсы көмек сұрау үшін"], correct: 1 },
{ q: "Қидандар 1128 жылы қандай қаланы басып алды?", options: ["Бұхара", "Самарқан", "Баласағұн", "Отырар"], correct: 2 },
{ q: "Қарақытай мемлекеті қай жылы Жетісуда құрылды?", options: ["1125 жылы", "1128 жылы", "1141 жылы", "1143 жылы"], correct: 1 },
{ q: "Қарақытай мемлекетінің негізін қалаған билеуші:", options: ["Күшлік хан", "Мұхаммед Хорезмшах", "Елюй Даши", "Шыңғыс хан"], correct: 2 },
{ q: "Қарақытай мемлекетінің ордасы мәтінде қалай көрсетілген?", options: ["Ғұзорда", "Самарқанда", "Бұхарада", "Баласағұнда"], correct: 0 },
{ q: "1141 жылы болған Қатуан шайқасында Елюй Даши кімдердің әскерін талқандады?", options: ["Найман-қыпшақ әскерін", "Біріккен салжұқ-қарахан әскерін", "Қытай-моңғол әскерін", "Хорезмшах-найман әскерін"], correct: 1 },
{ q: "Қатуан шайқасы болған жылды анықтаңыз.", options: ["1128 жыл", "1141 жыл", "1143 жыл", "1212 жыл"], correct: 1 },
{ q: "Қарақытайлар басып алған аймақтарды көрсетіңіз.", options: ["Жетісу, Мауараннахр, Шығыс Түркістан", "Еділ бойы, Қырым, Кавказ", "Моңғолия, Қытай, Корея", "Дешті Қыпшақ, Сібір, Еділ бойы"], correct: 0 },
{ q: "Қарақытайлар Хорезмшахтар мемлекетінің билеушісін жеңгеннен кейін не істетті?", options: ["Мемлекетін жойды", "Оны өз әскеріне қосты", "Жыл сайын алым-салық төлеуге мәжбүр етті", "Баласағұнға көшірді"], correct: 2 },
{ q: "Қарақытайлар Қарахан әулетіне қатысты қандай саясат жүргізді?", options: ["Қарахан әулетін толық жойды", "Қарахан әулетін биліктен кетіріп, елді тікелей басқарды", "Оларды вассал етіп, алым-салық алумен шектелді", "Қарахан әулетімен одақ құрды"], correct: 2 },
{ q: "Қарақытайлар Қарахандардың басқару жүйесіне қатысты қандай саясат ұстанды?", options: ["Басқару жүйесін түбегейлі өзгертті", "Басқару жүйесіне өзгеріс енгізбеді", "Барлық билікті дінбасыларға берді", "Әскери басқару жүйесін енгізді"], correct: 1 },
{ q: "Қарақытай билеушісінің лауазымы қалай аталды?", options: ["Қаған", "Хан", "Гурхан", "Сұлтан"], correct: 2 },
{ q: "«Гурхан» атауының мағынасы қандай?", options: ["Ұлы қолбасшы", "Хандардың ханы", "Ел билеушісі", "Құдайдың елшісі"], correct: 1 },
{ q: "Гурханның бас ордасы қай жерде орналасты?", options: ["Іле өзенінің бойында", "Баласағұнға жақын, Шу өзенінің бойында", "Сырдария бойында", "Бұхара қаласында"], correct: 1 },
{ q: "Гурханның салық саясатына қатысты дұрыс тұжырымды анықтаңыз.", options: ["Салықты толық жойды", "Әр отбасынан бір динардан салық алды", "Тек саудагерлерден салық алды", "Әр отбасынан он динардан салық алды"], correct: 1 },
{ q: "Гурхан өз маңайындағыларға енші жер бермеді. Оның басты себебі қандай болды?", options: ["Жер жетіспеді", "Дінге байланысты тыйым салынды", "Өзара қырқыстан және олардың күшейіп кетуінен қауіптенді", "Халықтың наразылығынан қорықты"], correct: 2 },
{ q: "Елюй Даши қай жылы қайтыс болды?", options: ["1141 жылы", "1143 жылы", "1185 жылы", "1212 жылы"], correct: 1 },
{ q: "Елюй Даши қайтыс болғаннан кейін билік кімнің қолына өтті?", options: ["Оның ұлының", "Оның қызының", "Оның жесірінің", "Күшлік ханның"], correct: 2 },
{ q: "Қарақытайларда билікке мұрагерлік ету құқығына кімдер ие болды?", options: ["Тек ер адамдар", "Тек әскербасылар", "Ерлер және билеуші рудың әйелдері", "Тек дінбасылар"], correct: 2 },
{ q: "Қарақытай тарихындағы билікке ие болған әйелдердің бірі кім?", options: ["Елюй Дашидің қызы", "Күшлік ханның қызы", "Мұхаммед Хорезмшахтың әйелі", "Баласағұн билеушісінің қызы"], correct: 0 },
{ q: "XII ғасырдың ортасынан бастап қарақытайлардың салық саясаты қалай өзгерді?", options: ["Салық мөлшерін азайтты", "Салық жинауды тоқтатты", "Ашық тонауға көшті", "Сауда салығын ғана енгізді"], correct: 2 },
{ q: "XII ғасырдың соңында қарақытайлардың қандай діни саясаты күшейді?", options: ["Барлық діндерге тыйым салынды", "Мұсылмандарды қудалау басталды", "Христиандықты міндеттеді", "Буддизмге тыйым салынды"], correct: 1 },
{ q: "Қарақытайлардың Жетісудағы билігінің әлсіреуіне әсер еткен факторды көрсетіңіз.", options: ["Сауданың дамуы", "Бейбіт тұрғындарды тонау және мұсылмандарды ығыстыру", "Қытаймен достық қатынас орнатуы", "Салықтарды жоюы"], correct: 1 },
{ q: "Қарақытайлар соғысып, жеңіліске ұшыраған Хорезмшах билеушісі:", options: ["Елюй Даши", "Күшлік хан", "Мұхаммед", "Шыңғыс хан"], correct: 2 },
{ q: "Қарақытай билеушісін кім тұтқындады?", options: ["Қытай әскерлері", "Күшлік хан және оның одақтастары", "Салжұқтар", "Қарахандар"], correct: 1 },
{ q: "Қарақытай мемлекеті қай жылы өмір сүруін тоқтатты?", options: ["1208 жылы", "1212 жылы", "1218 жылы", "1221 жылы"], correct: 1 },
{ q: "Оқиғалардың дұрыс хронологиялық ретін анықтаңыз:\n\n1. Елюй Дашидің Қатуан шайқасында жеңіске жетуі\n2. Қарақытай мемлекетінің өмір сүруін тоқтатуы\n3. Қидандардың Баласағұнды басып алуы\n4. Ляо мемлекетінің құлауы", options: ["4 – 3 – 1 – 2", "3 – 4 – 1 – 2", "4 – 1 – 3 – 2", "1 – 3 – 4 – 2"], correct: 0 },
{ q: "Қарақытайлардың Жетісуға алғаш қоныстанған кездегі саяси ұстанымы қандай болды?", options: ["Жергілікті билеушілерге қарсы бірден соғыс бастады", "Жергілікті билеушілерге бағынатындықтарын білдірді", "Хорезмшахтарға тәуелді болды", "Қытай билігін мойындады"], correct: 1 },
{ q: "Қарақытайлар бастапқыда Жетісуға қандай мақсатпен шақырылды?", options: ["Сауда жолдарын қорғау үшін", "Қытай әскеріне қарсы күресу үшін", "Бағынбаған тайпаларға қарсы күресуге көмектесу үшін", "Исламды тарату үшін"], correct: 2 },
{ q: "Қарақытайлардың әскерінде қандай өзгеріс жасалды?", options: ["Әскер таратылды", "Әскер тәртібі күшейтілді", "Әскер тек жалдамалылардан құрылды", "Әскер саны қысқартылды"], correct: 1 },
{ q: "Гурханның өкілетті басқарушылары қандай қызмет атқарды?", options: ["Тек әскер басқарды", "Тек сот қызметін атқарды", "Бағыныштыларды бақылап, салық жинады", "Сауда керуендерін басқарды"], correct: 2 },
{ q: "Қарақытайлар қай аймақты басып алғаннан кейін Мауараннахрдың орталық бөлігін де өз құрамына қосты?", options: ["Бұхараны", "Баласағұнды", "Отырарды", "Таразды"], correct: 0 },
{ q: "Қарақытайлардың Қарахандықтарға қатысты саясатының ерекшелігі неде болды?", options: ["Олардың мәдениетін толық жойды", "Басқару жүйесін сақтап, вассалдық тәуелділік орнатты", "Қарахан әулетін бірден жойды", "Барлық жерді жергілікті халыққа бөліп берді"], correct: 1 },
{ q: "Қарақытайлар билігінің соңғы кезеңінде Жетісуда қандай қозғалыс күшейді?", options: ["Мұсылмандардың қозғалысы", "Қытайлықтардың көтерілісі", "Қыпшақтардың қозғалысы", "Саудагерлердің қозғалысы"], correct: 0 },
{ q: "Қарақытайлардың Жетісудағы билігінің әлсіреуіне төмендегі оқиғалардың қайсысы тікелей ықпал етті?", options: ["Халықтың әл-ауқатының көтерілуі", "Бейбіт тұрғындардың тонауға ұшырауы", "Салықтардың жойылуы", "Сауда қатынастарының күшеюі"], correct: 1 },
{ q: "1208 жылы Жетісуға келген Күшлік бастаған наймандарды бұл өңірге не әкелді?", options: ["Хорезмшахтар", "Қарахандар", "Шыңғыс ханның Монғолиядан ығыстыруы", "Қытай билеушілері"], correct: 2 },
{ q: "1208 жылы Күшлік бастаған наймандардың Жетісуға келуінің нәтижесі қандай болды?", options: ["Қарақытайлардың саяси ықпалы күшейді", "Қарақытайлар Жетісудағы саяси ықпалынан айырылды", "Қарахан мемлекеті қайта құрылды", "Хорезмшахтар Жетісуды басып алды"], correct: 1 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>

391
qarlyq-kaganaty.html Normal file
View File

@ -0,0 +1,391 @@
<!-- no-design-system -->
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Қарлұқ қағанаты</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🐆</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Қарлұқ қағанаты</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">35</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 35</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "VII ғасырдың соңынан бастап қарлұқтар қай мемлекеттің ықпалында болды?", options: ["Батыс Түрік қағанаты", "Шығыс Түрік қағанаты", "Түргеш қағанаты", "Ұйғыр қағанаты"], correct: 1 },
{ q: "Қарлұқтар мекендеген негізгі аймақты көрсетіңіз.", options: ["Алтай мен Балқаш көлі аралығы", "Еділ мен Жайық аралығы", "Арал мен Каспий аралығы", "Сырдария мен Әмудария аралығы"], correct: 0 },
{ q: "Ибн әл-Факих қарлұқтар туралы қандай пікір айтқан?", options: ["«Олар — көне оғыздар»", "«Олар — көне түркілер»", "«Олар — ежелгі арабтар»", "«Олар — қыпшақтар»"], correct: 1 },
{ q: "Ибн әл-Факих қарлұқтар туралы мәлімет қалдырған ғасыр:", options: ["VIII ғасыр", "IX ғасыр", "X ғасыр", "XI ғасыр"], correct: 2 },
{ q: "Біріккен ұйғыр және қарлұқ күштері қай билікті құлатты?", options: ["Түргештердің билігін", "Шығыс түркілердің билігін", "Саманилер билігін", "Қарахандықтардың билігін"], correct: 1 },
{ q: "Орталық Азияда 744–840 жылдары өмір сүрген мемлекет:", options: ["Түргеш қағанаты", "Қарлұқ қағанаты", "Ұйғыр қағанаты", "Қарахан мемлекеті"], correct: 2 },
{ q: "Ұйғыр тайпаларының билеушісі қандай лауазым иеленді?", options: ["Жабғу", "Шад", "Қаған", "Тархан"], correct: 2 },
{ q: "Ұйғыр қағанаты құрамында қарлұқтар көсемінің лауазымы:", options: ["Қаған", "Жабғу", "Елбасы", "Хан"], correct: 1 },
{ q: "Қарлұқтардың ұйғырларға қарсы дербестік үшін күресі немен аяқталды?", options: ["Қарлұқтардың жеңісімен", "Ұйғырлардың жеңілісімен", "Қарлұқтардың жеңілісімен", "Бейбіт келісіммен"], correct: 2 },
{ q: "Қарлұқтар батысқа қарай қай жылы қашты?", options: ["704 жылы", "716 жылы", "746 жылы", "756 жылы"], correct: 2 },
{ q: "746 жылы қарлұқтар қай бағытқа қоныс аударды?", options: ["Шығысқа", "Батысқа", "Солтүстікке", "Оңтүстікке"], correct: 1 },
{ q: "Жетісуға келген қарлұқтар қай тайпалардың қарсылығына кездесті?", options: ["Қыпшақтардың", "Наймандардың", "Оғыздардың", "Керейлердің"], correct: 2 },
{ q: "VIII ғасырдың ортасында қарлұқтар оғыздарды қай бағытқа ығыстырды?", options: ["Іле аңғарына", "Сырдарияның төменгі ағысына", "Ертістің жоғарғы ағысына", "Еділ бойына"], correct: 1 },
{ q: "756 жылы қарлұқтар қай тайпаны Жетісудан ығыстырды?", options: ["Оғыздарды", "Қимақтарды", "Түргештерді", "Қыпшақтарды"], correct: 2 },
{ q: "756 жылғы оқиғаның нәтижесі:", options: ["Қарлұқтар Жетісуда саяси үстемдік орнатты", "Түргештер қайта күшейді", "Ұйғыр қағанаты құрылды", "Саманилер Жетісуды басып алды"], correct: 0 },
{ q: "VIII–X ғасырларда қарлұқ тайпаларының қоныстанған аумағы:", options: ["Жоңғар Алатауынан Сырдарияға дейін", "Алтайдан Еділге дейін", "Каспийден Қара теңізге дейін", "Ертістен Оралға дейін"], correct: 0 },
{ q: "Қарлұқтардың жерін батыстан шығысқа дейін жүріп өтуге қанша уақыт қажет болған?", options: ["10 күн", "20 күн", "30 күн", "40 күн"], correct: 2 },
{ q: "Қарлұқтардың жетекші тайпасы:", options: ["Бұлақ", "Шігіл", "Яғма", "Қаңлы"], correct: 0 },
{ q: "«Худдуд әл-Алам» дерегінде қарлұқтар жерінде қанша қала мен қоныс болғаны көрсетіледі?", options: ["15", "20", "25", "30"], correct: 2 },
{ q: "840 жылы қарлұқтардың қолдауымен Ұйғыр қағанатын кімдер құлатты?", options: ["Саманилер", "Енисей қырғыздары", "Түргештер", "Оғыздар"], correct: 1 },
{ q: "840 жылы қарлұқ жабғуы қандай лауазымды иеленді?", options: ["Хан", "Шад", "Қаған", "Тархан"], correct: 2 },
{ q: "Ұйғырлар мен қарлұқтардың бақталастығы немен аяқталды?", options: ["Ұйғырлардың жеңісімен", "Қарлұқтардың жеңісімен", "Саманилердің жеңісімен", "Бітім жасалуымен"], correct: 1 },
{ q: "Қарлұқ кезеңінде Қазақстан аумағында қандай үрдіс белсенді жүрді?", options: ["Арабтандыру", "Моңғолдандыру", "Түркілендіру", "Парсыландыру"], correct: 2 },
{ q: "Қарлұқ кезеңіндегі түркілендіру үрдісі қай ғасырларды қамтыды?", options: ["VI–VII ғасырлар", "VII–VIII ғасырлар", "VIII–X ғасырлар", "X–XII ғасырлар"], correct: 2 },
{ q: "Арабтар үшін Жетісудың маңыздылығының негізгі себебі:", options: ["Тек әскери бекіністердің болуы", "Стратегиялық және сауда-экономикалық маңызы", "Мұнай кен орындарының болуы", "Егіншілік аймағы болуы"], correct: 1 },
{ q: "IX ғасырдың 20-жылдарында Орталық Азияда билікке келген әулет:", options: ["Қарахандықтар", "Саманилер", "Селжұқтар", "Аббасилер"], correct: 1 },
{ q: "840 жылы саманилер түркілерге қарсы қандай соғыс жариялады?", options: ["«Ұлы жорық»", "«Қасиетті соғыс»", "«Азаттық соғысы»", "«Шығыс жорығы»"], correct: 1 },
{ q: "840 жылы саманилер басып алған қала:", options: ["Тараз", "Баласағұн", "Испиджаб", "Суяб"], correct: 2 },
{ q: "Испиджабтың тарихи маңызы:", options: ["Қарлұқтардың астанасы болды", "Оңтүстік Қазақстанда исламды таратудың орталығына айналды", "Ұйғырлардың саяси орталығы болды", "Түргештердің әскери орталығы болды"], correct: 1 },
{ q: "IX ғасырдың соңында саманилер басып алған қала:", options: ["Тараз", "Суяб", "Баласағұн", "Қойлық"], correct: 0 },
{ q: "Саманилердің жорықтары Қарлұқ қағанатына қалай әсер етті?", options: ["Қағанатты күшейтті", "Қағанатты әлсіретті", "Жаңа астана салуға мүмкіндік берді", "Қарлұқтардың аумағын кеңейтті"], correct: 1 },
{ q: "Қарлұқ қағанатына Қашғар жағынан қауіп төнген кезең:", options: ["VIII ғасырдың басы", "VIII ғасырдың ортасы", "IX ғасырдың басы", "X ғасырдың бірінші жартысы"], correct: 3 },
{ q: "940 жылы Қашғар түркілері қай қаланы басып алды?", options: ["Таразды", "Испиджабты", "Баласағұнды", "Суябты"], correct: 2 },
{ q: "Қарлұқ қағанатының өмір сүруін тоқтатуына тікелей себеп болған оқиға:", options: ["Түргештердің қайта күшеюі", "Баласағұнның Қашғар түркілері тарапынан басып алынуы", "Оғыздардың Жетісуға қайта келуі", "Енисей қырғыздарының шабуылы"], correct: 1 },
{ q: "Қарлұқ дәуірінің сәулет өнеріне жататын Ақыртас ғимараты қай жерде орналасқан?", options: ["Түркістан облысында", "Жамбыл облысында", "Алматы облысында", "Қызылорда облысында"], correct: 1 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>

401
qimaq-kaganaty.html Normal file
View File

@ -0,0 +1,401 @@
<!-- no-design-system -->
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Қимақ қағанаты</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏹</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Қимақ қағанаты</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">45</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 45</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "Қимақтар туралы мәліметтер кездесетін деректерді анықтаңыз.", options: ["Араб, парсы, түркі және қытай деректерінде", "Рим, грек және үнді деректерінде", "Тек араб деректерінде", "Тек қытай деректерінде"], correct: 0 },
{ q: "Қимақтар бастапқыда қай аймақта өмір сүрген?", options: ["Сырдария бойында", "Батыс Моңғолия даласында", "Жетісу жерінде", "Еділ бойында"], correct: 1 },
{ q: "Қимақтар Батыс Моңғолиядан Алтай таулары мен Ертіс бойына қай ғасырда көшті?", options: ["VI ғасырдың ортасында", "VIII ғасырдың басында", "VII ғасырдың ортасында", "IX ғасырдың соңында"], correct: 2 },
{ q: "Қимақ тайпасының өз алдына бөлектенуі қай оқиғамен байланысты болды?", options: ["Ұйғыр қағанатының құрылуымен", "Қарахан мемлекетінің құрылуымен", "Қыпшақ хандығының құрылуымен", "Батыс Түрік қағанатының құлауымен"], correct: 3 },
{ q: "Қимақ тайпасының өз алдына бөлектенуі қай жылы іске асты?", options: ["656 жылы", "603 жылы", "840 жылы", "751 жылы"], correct: 0 },
{ q: "VIII–IX ғасырларда Солтүстік-шығыс Қазақстан аумағында не қалыптасты?", options: ["Қарахан мемлекеті", "Қимақ тайпалар одағы", "Түргеш қағанаты", "Оғыз мемлекеті"], correct: 1 },
{ q: "Қимақтар VIII–IX ғасырларда қай аумаққа берік орнықты?", options: ["Сырдариядан Аралға дейін", "Еділден Жайыққа дейін", "Ертістен Жоңғар қақпасына дейін", "Алтайдан Каспий теңізіне дейін"], correct: 2 },
{ q: "Кейін қимақтар батыста қай өзенге дейін жылжыды?", options: ["Сырдарияға", "Ілеге", "Есілге", "Жайыққа"], correct: 3 },
{ q: "Қимақ тайпасының басшысы қандай лауазым иеленді?", options: ["Шадтүтүк", "Қаған", "Сұлтан", "Ябғу"], correct: 0 },
{ q: "«Шадтүтүк» лауазымының мағынасы қандай?", options: ["Жоғарғы қолбасшы", "Билеуші көсем", "Қала басқарушысы", "Әскербасы"], correct: 1 },
{ q: "VIII ғасырдың соңында Қимақ бірлестігіне қай тайпалар көптеп енді?", options: ["Оғыздар", "Түргештер", "Қыпшақтар", "Қарлұқтар"], correct: 2 },
{ q: "Қимақ қағанатының құрылуы қай кезеңде аяқталды?", options: ["VIII ғасырдың басында", "X ғасырдың ортасында", "VII ғасырдың соңында", "IX ғасырдың ортасында"], correct: 3 },
{ q: "840 жылы Қимақтарға қандай оқиғадан кейін тайпалардың бір бөлігі қосылды?", options: ["Ұйғыр қағанаты құлағаннан кейін", "Батыс Түрік қағанаты құлағаннан кейін", "Қарахан мемлекеті әлсірегеннен кейін", "Оғыз мемлекеті ыдырағаннан кейін"], correct: 0 },
{ q: "Қимақ тайпалық одағының басшысы қандай лауазым иеленді?", options: ["Шадтүтүк", "Қаған", "Тархан", "Ябғу"], correct: 1 },
{ q: "Қимақтардың батысқа қоныс аударуына әсер еткен себептердің бірі:", options: ["Теңіз саудасының дамуы", "Егіншіліктің әлсіреуі", "Жайылым қажеттілігі", "Қалалардың көбеюі"], correct: 2 },
{ q: "Қимақтардың батысқа қоныс аударуына әсер еткен сыртқы күштердің бірі:", options: ["Қарахандықтардың қысымы", "Ұйғыр қағанатының қысымы", "Оғыздардың қысымы", "Түргештердің қысымы"], correct: 1 },
{ q: "Қимақтардың қоныс аударуына байланысты қақтығысқан халықтардың бірі:", options: ["Енисей қырғыздары", "Қарақытайлар", "Наймандар", "Үйсіндер"], correct: 0 },
{ q: "Араб ғалымы әл-Идриси қимақтардың қанша қаласын атаған?", options: ["7", "10", "16", "20"], correct: 2 },
{ q: "Әл-Идриси атаған қимақ қалаларының басым бөлігі қай аймақтарда орналасқан?", options: ["Сырдария мен Арал маңында", "Ертіс пен Алакөл аймағында", "Іле мен Шу бойында", "Еділ мен Каспий маңында"], correct: 1 },
{ q: "Қимақтардың негізгі шаруашылығы қандай болды?", options: ["Суармалы егіншілік", "Балық аулау", "Қолөнер", "Көшпелі мал шаруашылығы"], correct: 3 },
{ q: "Қимақ қағанының Ертіс бойындағы ордасы орналасқан қала:", options: ["Карантия", "Тараз", "Имақия", "Баласағұн"], correct: 2 },
{ q: "Қимақтардың екінші астанасы қай қала болды?", options: ["Имақия", "Карантия", "Отырар", "Суяб"], correct: 1 },
{ q: "Карантия қаласы қай аймақта орналасқан?", options: ["Алакөл маңында", "Ертістің жоғарғы ағысында", "Сырдария бойында", "Жайық бойында"], correct: 0 },
{ q: "Қимақтар қай халықпен бейбіт қарым-қатынас орнатты?", options: ["Қарахандықтармен", "Енисей қырғыздарымен", "Оғыздармен", "Ұйғырлармен"], correct: 2 },
{ q: "Қимақ жеріне бірнеше рет әскери жорық жасап, Ертіске дейін жеткендер:", options: ["Оғыздар", "Қарахандықтар", "Енисей қырғыздары", "Ұйғырлар"], correct: 1 },
{ q: "IX ғасырдың ортасына қарай қимақтар қай аралықтағы тайпаларды біріктірді?", options: ["Сырдариядан Каспийге дейін", "Алтайдан Жайыққа дейін", "Ертістен Аралға дейін", "Жетісудан Еділге дейін"], correct: 1 },
{ q: "Х ғасырдың басында Қимақ қағанатының шекарасында қандай жағдай орнады?", options: ["Үздіксіз соғыс басталды", "Мемлекет ыдырады", "Тыныштық орнады", "Қағанат әлсіреді"], correct: 2 },
{ q: "Қимақтармен сауда жолдарының болғанын дәлелдейтін бағыттардың бірі:", options: ["Еділ бойы мен Орталық Азиядан", "Үндістан мен Қытайдан ғана", "Еуропа мен Византиядан", "Иран мен Арабиядан ғана"], correct: 0 },
{ q: "Ұлы Жібек жолы қай жердегі қимақ қағанының ордасына дейін жеткен?", options: ["Алакөлдегі Карантияға", "Ертістегі қимақ қағанының ордасына", "Жайықтағы қимақ қаласына", "Алтайдағы бекініске"], correct: 1 },
{ q: "Қимақ мемлекетінің ыдырауына алып келген ішкі себептердің бірі:", options: ["Сауда жолдарының тоқтауы", "Егіншіліктің дамуы", "Жеке жер иеліктері билеушілерінің дербестікке ұмтылуы", "Қалалардың жойылуы"], correct: 2 },
{ q: "Қимақ мемлекетінің ыдырауына әсер еткен қыпшақтарға қатысты себеп:", options: ["Қыпшақтардың жаңа дін қабылдауы", "Қыпшақ көсемдерінің дербес мемлекет үшін күресі", "Қыпшақтардың батысқа көшуден бас тартуы", "Қыпшақтардың егіншілікке көшуі"], correct: 1 },
{ q: "Қимақ қағанатының құлдырау белгілері қай кезден байқала бастады?", options: ["IX ғасырдың басынан", "X ғасырдың екінші жартысынан", "XI ғасырдың ортасынан", "VIII ғасырдың соңынан"], correct: 1 },
{ q: "Қимақ қағанаты қай ғасырдың басында өмір сүруін тоқтатты?", options: ["IX ғасырдың басында", "X ғасырдың басында", "XI ғасырдың басында", "XII ғасырдың басында"], correct: 2 },
{ q: "Қимақ қағанатының жер аумағы кейін кімдерге өтті?", options: ["Оғыздарға", "Қарлұқтарға", "Қарахандықтарға", "Қыпшақтарға"], correct: 3 },
{ q: "Қимақ қағаны қандай қызмет атқарды?", options: ["Қағанаттың жоғарғы бас қолбасшысы болды", "Тек діни қызмет атқарды", "Сауда жолдарын ғана басқарды", "Қалалардың құрылысын басқарды"], correct: 0 },
{ q: "Қаған жер иеліктерін кімдерге үлестірді?", options: ["Саудагерлерге", "Тайпа көсемдеріне", "Диқандарға", "Қолөнершілерге"], correct: 1 },
{ q: "Тайпа көсемдеріне жер иеліктері қандай негізде берілді?", options: ["Облы байлығына қарай", "Жасына қарай", "Әскери қызметте сіңірген еңбегіне қарай", "Шыққан тегіне ғана қарай"], correct: 2 },
{ q: "Қимақ халқы қалай бөлінді?", options: ["Облыстарға", "Ұлыстарға", "Жүздерге", "Иеліктерге"], correct: 3 },
{ q: "Иелік билеушілері қаған әскеріне не беріп отырды?", options: ["Белгіленген мөлшерде жасақ", "Азық-түлік салығын ғана", "Малдың жартысын", "Сауда салығын"], correct: 0 },
{ q: "IX ғасырдағы қимақ билеушісінің әскері қандай жасақ ретінде құрылды?", options: ["Жаяу әскер", "Рулар жасағы", "Қала жасағы", "Құлдар жасағы"], correct: 1 },
{ q: "IX ғасырдағы қимақ әскерінің негізгі бөлігі кімдерден тұрды?", options: ["Жаяу әскерлерден", "Садақшылардан ғана", "Салт аттылардан", "Теңізшілерден"], correct: 2 },
{ q: "Қимақ қағанатының құрамына қанша тайпа кірді?", options: ["5 тайпа", "6 тайпа", "7 тайпа", "9 тайпа"], correct: 2 },
{ q: "Қимақ қағанаты құрамындағы сан жағынан басым тайпа:", options: ["Оғыздар", "Қыпшақтар", "Қарлұқтар", "Түргештер"], correct: 1 },
{ q: "Қимақтардың көне түркі жазуын қолданғанын дәлелдейтін археологиялық дерек қай жерлерден табылған?", options: ["Сырдария мен Аралдан", "Еділ мен Каспийден", "Ертіс бойы мен Тарбағатай тауларынан", "Іле мен Шу аңғарларынан"], correct: 2 },
{ q: "Қимақтардың діни наным-сенімдерін дұрыс көрсетіңіз.", options: ["Буддизмді ұстанып, монастырьлар салды", "Исламды мемлекеттік дін етті", "Христиан дінін қабылдады", "Тәңірге табынып, ата-баба рухына сиынды"], correct: 3 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>

406
qypshaqtar-tarihy.html Normal file
View File

@ -0,0 +1,406 @@
<!-- no-design-system -->
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Қыпшақтар тарихы</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🐎</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Қыпшақтар тарихы</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">50</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 50</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "Қыпшақ этносы мен мемлекеттілігінің қалыптасуының алғашқы кезеңі қайсысы?", options: ["VII–VIII ғасырлар", "VIII–ХІ ғасырлар", "ХІ–ХІІІ ғасырлар", "ХІІ–ХІV ғасырлар"], correct: 0 },
{ q: "VII–VIII ғасырларда қыпшақтар қай мемлекеттің құрамында болды?", options: ["Қарахан мемлекеті", "Батыс Түрік қағанаты", "Қимақ қағанаты", "Хорезмшахтар мемлекеті"], correct: 1 },
{ q: "VIII–ХІ ғасырларда қыпшақтар қай мемлекеттің құрамында болды?", options: ["Қимақ қағанаты", "Батыс Түрік қағанаты", "Алтын Орда", "Қарахан мемлекеті"], correct: 0 },
{ q: "ХІ–ХІІІ ғасырларда қыпшақтар қандай мемлекет құрды?", options: ["Қимақ қағанаты", "Қарахан мемлекеті", "Дербес Қыпшақ хандығы", "Хорезмшахтар мемлекеті"], correct: 2 },
{ q: "«Қыпшақ» этнонимі алғаш рет қай ғасырдағы көне түркі руна ескерткішінде кездеседі?", options: ["VI ғасыр", "VII ғасыр", "VIII ғасыр", "IX ғасыр"], correct: 2 },
{ q: "Русьте қыпшақтар қалай аталды?", options: ["Командар", "Половецтер", "Қимақтар", "Оғыздар"], correct: 1 },
{ q: "Еуропада қыпшақтар қалай аталды?", options: ["Половецтер", "Командар", "Қарақытайлар", "Қимақтар"], correct: 1 },
{ q: "VIII–ХІ ғасырлар аралығында қыпшақтар тарихы қай тайпаның тарихымен тығыз байланысты болды?", options: ["Оғыздармен", "Қарлұқтармен", "Қимақтармен", "Наймандармен"], correct: 2 },
{ q: "Қыпшақтар Қимақ мемлекетінің қай қанатын құрады?", options: ["Шығыс қанатын", "Оңтүстік қанатын", "Солтүстік қанатын", "Батыс қанатын"], correct: 3 },
{ q: "Қимақ қағанаты қай ғасырдың басында құлады?", options: ["X ғасырдың басында", "XI ғасырдың басында", "XII ғасырдың басында", "XIII ғасырдың басында"], correct: 1 },
{ q: "Қимақ қағанаты құлағаннан кейін оның жері кімдердің қолына өтті?", options: ["Оғыз хандарының", "Қарахан билеушілерінің", "Қыпшақ хандарының", "Хорезмшахтардың"], correct: 2 },
{ q: "Қыпшақтар этнос ретінде қай аумақта VIII ғасырда қалыптасты?", options: ["Батыс және Оңтүстік Қазақстанда", "Орталық және Шығыс Қазақстанда", "Солтүстік және Батыс Қазақстанда", "Жетісу мен Сырдария бойында"], correct: 1 },
{ q: "XI ғасырдың ортасында қыпшақтар кімдерді Сырдария аймағы мен Каспий даласынан ығыстырды?", options: ["Қимақтарды", "Қарахандарды", "Оғыздарды", "Қарлұқтарды"], correct: 2 },
{ q: "Қыпшақтар батысқа жылжу барысында қай өзеннен өтті?", options: ["Ертіс", "Іле", "Есіл", "Еділ"], correct: 3 },
{ q: "Қыпшақтар батысқа жылжу барысында қай өзенге дейін жетті?", options: ["Әмударияға", "Дунайға", "Сырдарияға", "Жайыққа"], correct: 1 },
{ q: "Қыпшақтардың батысқа жылжуы нәтижесінде байланыс орнатқан халықтардың бірі?", options: ["Русь", "Жапондар", "Үнділер", "Қытайлар"], correct: 0 },
{ q: "XI ғасырда қыпшақтар қай аумаққа үстемдік етті?", options: ["Тек Жетісуға", "Тек Сырдария бойына", "Жетісумен қатар бүкіл Қазақстан жеріне", "Тек Батыс Қазақстанға"], correct: 2 },
{ q: "XI ғасырда қыпшақтар қандай аумақтағы ірі тайпалық одақ саналды?", options: ["Дунайдан Кавказға дейін", "Алтайдан Дунайға дейін", "Ертістен Үндістанға дейін", "Жетісудан Қытайға дейін"], correct: 1 },
{ q: "XI–XIII ғасырларда Еуразияның бүкіл далалық аймағы қалай аталды?", options: ["Моғолстан", "Дешті Қыпшақ", "Жетісу", "Түркістан"], correct: 1 },
{ q: "«Дешті Қыпшақ» атауының мағынасы қандай?", options: ["Қыпшақ елі", "Қыпшақ тауы", "Қыпшақ даласы", "Қыпшақ өзені"], correct: 2 },
{ q: "XII ғасырдың басында қыпшақтар қай аумақта үстемдік етті?", options: ["Ертістен Сырдарияға дейін", "Алтайдан Дунайға дейінгі Ұлы Далада", "Еділден Кавказға дейін", "Жетісудан Қара теңізге дейін"], correct: 1 },
{ q: "Дешті Қыпшақ даласы неше ірі бірлестікке бөлінді?", options: ["Екі", "Үш", "Төрт", "Бес"], correct: 0 },
{ q: "Батыс қыпшақ бірлестігі қай аумақты иеленді?", options: ["Еділден Алтайға дейін", "Дунайдан Еділге дейін", "Ертістен Дунайға дейін", "Сырдариядан Еділге дейін"], correct: 1 },
{ q: "Батыс қыпшақ бірлестігін қай әулеттік ру басқарды?", options: ["Елбөрілі", "Тоқсаба", "Қият", "Арғын"], correct: 1 },
{ q: "Шығыс қыпшақ бірлестігі қай аумақты қамтыды?", options: ["Дунайдан Еділге дейін", "Еділден Алтайға дейін", "Алтайдан Дунайға дейін", "Жайықтан Дунайға дейін"], correct: 1 },
{ q: "Шығыс қыпшақ бірлестігін қай ру басқарды?", options: ["Тоқсаба", "Елбөрілі", "Қоңырат", "Найман"], correct: 1 },
{ q: "Қыпшақ хандығы неше қанатқа бөлінді?", options: ["Бір", "Екі", "Үш", "Төрт"], correct: 1 },
{ q: "Қыпшақ хандығының оң қанатының ордасы қай қалада орналасты?", options: ["Сығанақ", "Сарайшық", "Отырар", "Баласағұн"], correct: 1 },
{ q: "Қыпшақ хандығының сол қанатының орталығы қай қала болды?", options: ["Сарайшық", "Тараз", "Сығанақ", "Түркістан"], correct: 2 },
{ q: "Қыпшақ хандығының қай қанаты ең қуатты болды?", options: ["Оң қанаты", "Батыс қанаты", "Сол қанаты", "Оңтүстік қанаты"], correct: 2 },
{ q: "Қыпшақ хандарының билігі қалай беріліп отырды?", options: ["Сайлау арқылы", "Тайпа ақсүйектерінің шешімімен", "Мұрагерлікпен әкеден балаға", "Әскери кеңес арқылы"], correct: 2 },
{ q: "Жекелеген қыпшақ руларының кімнен басқа өз билеушілері болды?", options: ["Қағаннан", "Жоғары ханнан", "Сұлтаннан", "Елбөрілі руынан"], correct: 1 },
{ q: "Қыпшақтардың саяси беделінің артуына байланысты басқа тайпалар не істеді?", options: ["Қыпшақтармен соғысты", "Қыпшақ жерінен көшіп кетті", "«Қыпшақ» этнонимін қабылдады", "Қимақ мемлекетіне қосылды"], correct: 2 },
{ q: "Қыпшақтар қазіргі қандай халықтардың ұлт ретінде қалыптасуына негіз қалады?", options: ["Қазақ, башқұрт, татар және басқалардың", "Қытай, моңғол, тибет халықтарының", "Парсы, араб, үнді халықтарының", "Орыс, украин, беларусь халықтарының"], correct: 0 },
{ q: "Қыпшақ қоғамындағы байлық немен өлшенді?", options: ["Жер көлемімен", "Алтын мөлшерімен", "Қала санымен", "Жылқы санымен"], correct: 3 },
{ q: "Малға жекеменшік қыпшақ қоғамында қандай құбылыстың негізін қалады?", options: ["Құлдықтың жойылуының", "Мүліктік теңсіздіктің", "Қалалардың көбеюінің", "Сауданың тоқтауын"], correct: 1 },
{ q: "Жайылымдарға билік ету және көшіп-қонуды реттеу құқығы кімдерге берілді?", options: ["Құлдарға", "Қарапайым малшыларға", "Қыпшақ хандары мен тайпа ақсүйектеріне", "Саудагерлерге"], correct: 2 },
{ q: "Қыпшақ қоғамында құқығы жоқ топ қалай аталды?", options: ["Яланкуг", "Коман", "Половец", "Елбөрілі"], correct: 0 },
{ q: "Қыпшақ қоғамындағы құлдардың саны негізінен қалай толықтырылды?", options: ["Сауда арқылы", "Әскери тұтқындар есебінен", "Салық төлеушілер есебінен", "Қоныс аударушылар есебінен"], correct: 1 },
{ q: "Қыпшақ хандығы қандай мемлекет болды?", options: ["Құл иеленушілік мемлекет", "Теократиялық мемлекет", "Ерте феодалдық мемлекет", "Демократиялық мемлекет"], correct: 2 },
{ q: "Хорезмшахтар бастапқыда қыпшақтарға қарсы жорықты қандай мақсатпен жүргізді?", options: ["Қыпшақтарды саудаға тарту үшін", "Исламды тарату мақсатында", "Қыпшақтармен одақ құру үшін", "Жайылымдарды кеңейту үшін"], correct: 1 },
{ q: "XII ғасырдың екінші жартысынан бастап хорезмдіктер қыпшақтарға қатысты қандай саясат жүргізе бастады?", options: ["Қыпшақтармен толық соғысты", "Қыпшақ жерінен көшіп кетті", "Қыпшақ ақсүйектерімен жақындасу саясатын", "Қыпшақтарды Руське қарсы қойды"], correct: 2 },
{ q: "Хорезмшахтар қыпшақ ақсүйектерімен жақындасу арқылы қандай мақсат көздеді?", options: ["Қыпшақтардың бүкіл ақсүйек қауымын ислам дініне енгізу", "Қыпшақтардың тәуелсіздігін күшейту", "Қыпшақ хандығын қалпына келтіру", "Қыпшақтарды Еуропаға көшіру"], correct: 0 },
{ q: "Қыпшақтар мен хорезмдіктердің күресін не тоқтатты?", options: ["Қарахан мемлекеті", "Оғыздардың шабуылы", "Моңғолдардың жаулап алушылық жорықтары", "Русьтің әскері"], correct: 2 },
{ q: "Орыс тіліндегі әскери іске байланысты көне түркі тілдерінен енген сөзді көрсетіңіз.", options: ["Колчан", "Парламент", "Республика", "Конституция"], correct: 0 },
{ q: "О. Сүлейменовтің қыпшақтар мен славяндар арасындағы байланысқа қатысты пікірі қай еңбегінде айтылды?", options: ["«Жолдар мен аймақтар»", "«Аз и Я»", "«Кодекс куманикус»", "«Дешті Қыпшақ»"], correct: 1 },
{ q: "ІХ ғасырдың ортасында «Жолдар мен аймақтар» еңбегін жазған ғалым кім?", options: ["Ибн Батута", "Махмұд Қашғари", "Ибн Хордадбек", "Плано Карпини"], correct: 2 },
{ q: "Ибн Хордадбек қыпшақтарға қатысты қандай мәлімет келтірді?", options: ["Қыпшақ хандарының шежіресін", "Қыпшақ тайпалары мен олардың 16 қаласы туралы", "Қыпшақтардың Русьпен соғыстарын", "Қыпшақтардың моңғолдармен соғысын"], correct: 1 },
{ q: "«Дешт» сөзінің түркі тіліндегі мағынасы қандай?", options: ["Қала", "Өзен", "Дала", "Таулар"], correct: 2 },
{ q: "Қыпшақ тілінің фольклор үлгілері сақталған ортағасырлық жазба ескерткіш қайсысы?", options: ["«Аз и Я»", "«Жолдар мен аймақтар»", "«Кодекс куманикус»", "«Диуани лұғат ат-түрік»"], correct: 2 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>

409
turgesh-kaganaty.html Normal file
View File

@ -0,0 +1,409 @@
<!-- no-design-system -->
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Түргеш қағанаты және соғдылар</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏹</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Түргеш қағанаты және соғдылар</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">52</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 52</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "Түргештер VI ғасырда қай мемлекеттің құрамында болды?", options: ["Шығыс Түрік қағанаты", "Батыс Түрік қағанаты", "Түрікмен мемлекеті", "Қарлұқ қағанаты"], correct: 1 },
{ q: "Түргештер Жетісуда өз саяси үстемдігін қай жылы орнатты?", options: ["603 жылы", "704 жылы", "715 жылы", "756 жылы"], correct: 1 },
{ q: "Түргештер негізінен қай аймақта қоныстанды?", options: ["Сырдария мен Әмудария аралығы", "Ертіс пен Есіл аралығы", "Іле мен Шу өзендерінің аралығы", "Еділ мен Жайық аралығы"], correct: 2 },
{ q: "Түргештер қандай екі топқа бөлінді?", options: ["Ақ және көк түргештер", "Сары және қара түргештер", "Қызыл және ақ түргештер", "Көк және қара түргештер"], correct: 1 },
{ q: "Шу түргештері қалай аталды?", options: ["Қара түргештер", "Ақ түргештер", "Сары түргештер", "Көк түргештер"], correct: 2 },
{ q: "Іле түргештері қалай аталды?", options: ["Сары түргештер", "Қара түргештер", "Ақ түргештер", "Көк түргештер"], correct: 1 },
{ q: "Түргештер әулетінің негізін қалаған қаған кім?", options: ["Сұлық", "Құтайба ибн Мүсілім", "Үшлік", "Махмұд Қашғари"], correct: 2 },
{ q: "Үшлік қағанның билік құрған жылдары:", options: ["680–690 жж.", "704–706 жж.", "715–738 жж.", "740–756 жж."], correct: 1 },
{ q: "Үшлік елді неше әкімшілік аймаққа бөлді?", options: ["10", "15", "20", "25"], correct: 2 },
{ q: "Үшлік бөлген әрбір әкімшілік аймақ қанша әскер шығарды?", options: ["5 000", "6 000", "7 000", "10 000"], correct: 2 },
{ q: "Үшлік қағанның бас ордасы қай қала болды?", options: ["Тараз", "Суяб", "Күнгіт", "Бұхара"], correct: 1 },
{ q: "Суяб қаласы қай өзеннің бойында орналасқан еді?", options: ["Іле", "Ертіс", "Шу", "Сырдария"], correct: 2 },
{ q: "Түргештердің екінші ордасы қай қалада орналасты?", options: ["Тараз", "Суяб", "Күнгіт", "Атлах"], correct: 2 },
{ q: "Күнгіт қаласы қай өзеннің бойында орналасқан?", options: ["Іле", "Шу", "Талас", "Сырдария"], correct: 0 },
{ q: "Түргеш қағанаты тарихындағы әйгілі билеушілерді көрсетіңіз.", options: ["Үшлік пен Сұлық", "Құтайба мен Сұлық", "Махмұд пен Үшлік", "Бумын мен Істеми"], correct: 0 },
{ q: "Түргештер қай билеушілерінің тұсында күшейіп, Жетісудағы ең қуатты мемлекетке айналды?", options: ["Үшлік пен Сұлықтың", "Құтайба мен Сұлықтың", "Махмұд Қашғари мен Үшліктің", "Қытай императорларының"], correct: 0 },
{ q: "Түргештердің оңтүстік-батыстағы басты қарсыласы кім болды?", options: ["Қарлұқтар", "Қытайлар", "Арабтар", "Соғдылар"], correct: 2 },
{ q: "Түргештер оңтүстік-шығыста кімдердің басқыншылығына қарсы тұрды?", options: ["Арабтардың", "Қытайлардың", "Қарлұқтардың", "Соғдылардың"], correct: 1 },
{ q: "Түргештерге шығыстан қандай мемлекет қауіп төндірді?", options: ["Батыс Түрік қағанаты", "Шығыс Түрік қағанаты", "Қарлұқ қағанаты", "Араб халифаты"], correct: 1 },
{ q: "Арабтар Орталық Азияға басқыншылық жорықтарын қай ғасырда бастады?", options: ["VI ғасырдың бірінші жартысында", "VI ғасырдың соңында", "VII ғасырдың екінші жартысында", "VIII ғасырдың соңында"], correct: 2 },
{ q: "Үшлік 706 жылы кімдерге көмек беруге тырысты?", options: ["Қытайларға", "Қарлұқтарға", "Арабтарға", "Соғдыларға"], correct: 3 },
{ q: "Түркі-соғды одағы араб әскерлеріне қай жерде соққы берді?", options: ["Тараз түбінде", "Бұхара түбінде", "Атлах түбінде", "Суяб түбінде"], correct: 1 },
{ q: "Бұхара түбіндегі шайқаста араб әскерлерінің қолбасшысы кім болды?", options: ["Сұлық", "Үшлік", "Құтайба ибн Мүсілім", "Махмұд Қашғари"], correct: 2 },
{ q: "Құтайба ибн Мүсілім одақтастар арасындағы қандай жағдайды пайдаланды?", options: ["Экономикалық дағдарысты", "Келісімшартты", "Келіспеушілікті", "Табиғи апатты"], correct: 2 },
{ q: "Сыртқы басқыншылармен белсенді күрес қай қағанның есімімен байланысты?", options: ["Үшлік", "Сұлық", "Құтайба", "Махмұд"], correct: 1 },
{ q: "Сұлық қаған қай жылдары билік құрды?", options: ["704–706 жж.", "706–715 жж.", "715–738 жж.", "740–756 жж."], correct: 2 },
{ q: "Сұлық қаған тұсында түргештердің ордасы қай қала болды?", options: ["Суяб", "Күнгіт", "Тараз", "Бұхара"], correct: 2 },
{ q: "Сұлық қағанның негізгі жетістіктерінің бірі:", options: ["Түргеш мемлекетін әлсіретуі", "Мемлекеттің бұрынғы қуатын қалпына келтіруі", "Қытайға бағынуы", "Арабтармен одақ құруы"], correct: 1 },
{ q: "Сұлықтың дипломатиялық және әскери шаралары қандай қауіптің алдын алды?", options: ["Қарлұқтардың қауіпін", "Соғдылардың қауіпін", "Қытай тарапынан төнген қауіпті", "Арабтардың қауіпін"], correct: 2 },
{ q: "Арабтар Сұлық қағанға қандай лақап ат қойды?", options: ["Жауынгер", "Сүзеген", "Батыр", "Жеңімпаз"], correct: 1 },
{ q: "Сүзеген деген лақап ат араб тілінде қалай аталды?", options: ["Әбу Музахим", "Әбу Насыр", "Әбу Әли", "Ибн Мүсілім"], correct: 0 },
{ q: "Сұлық қайтыс болғаннан кейін қай мемлекет Жетісуга басқыншылық саясатын қайта бастады?", options: ["Араб халифаты", "Қарлұқ қағанаты", "Қытай империясы", "Батыс Түрік қағанаты"], correct: 2 },
{ q: "Қытай әскерлері Таразды қай жылы басып алып, тонады?", options: ["704 жылы", "715 жылы", "740 жылы", "751 жылы"], correct: 2 },
{ q: "740 жылы Қытай әскерлері қай түргеш орталығын қиратты?", options: ["Таразды", "Суябты", "Күнгітті", "Бұхараны"], correct: 1 },
{ q: "Атлах шайқасы қай жылы болды?", options: ["740 жылы", "745 жылы", "751 жылы", "756 жылы"], correct: 2 },
{ q: "Атлах шайқасы қай қаланың маңында болды?", options: ["Суяб", "Тараз", "Бұхара", "Күнгіт"], correct: 1 },
{ q: "Атлах шайқасында кімдер соғысты?", options: ["Түргештер мен соғдылар", "Арабтар мен қытайлар", "Қарлұқтар мен соғдылар", "Түріктер мен арабтар"], correct: 1 },
{ q: "Атлах шайқасында түргештер мен қарлұқтар қай жақты қолдады?", options: ["Қытайларды", "Арабтарды", "Соғдыларды", "Шығыс Түріктерді"], correct: 1 },
{ q: "Атлах шайқасы қанша күнге созылды?", options: ["3 күн", "4 күн", "5 күн", "7 күн"], correct: 2 },
{ q: "Атлах шайқасының нәтижесінде қандай оқиға болды?", options: ["Араб әскері толық талқанданды", "Қытай әскері толық талқанданды", "Түргештер жеңілді", "Соғдылар Жетісудан кетті"], correct: 1 },
{ q: "Атлах шайқасының тарихи маңыздарының бірін көрсетіңіз.", options: ["Қытайлар Жетісудан қуылды", "Түргештер Қытайға бағынды", "Арабтар Жетісуды тастап кетті", "Қарлұқтар Орталық Азиядан кетті"], correct: 0 },
{ q: "Атлах шайқасынан кейін түркілер арасында не кеңінен тарала бастады?", options: ["Буддизм", "Христиандық", "Ислам мәдениеті", "Конфуцийлік"], correct: 2 },
{ q: "Түргеш мемлекеті қай жылы құлды?", options: ["740 жылы", "751 жылы", "756 жылы", "760 жылы"], correct: 2 },
{ q: "Түргеш мемлекетінің құлауына әсер еткен негізгі себептердің бірі:", options: ["Соғдылардың толық жеңісі", "Қытай және арабтармен соғыстар", "Исламның таралуы", "Сауданың дамуы"], correct: 1 },
{ q: "Соғдылардың Жетісуга қоныс аударуының негізгі себептерінің бірін В.В. Бартольд қалай түсіндірді?", options: ["Әскери міндеткерлік", "Сауда", "Мал шаруашылығының дамуы", "Түргештердің арнайы шақыруы"], correct: 1 },
{ q: "Соғдылардың Жетісуга қоныс аударуының себептерінің бірі қандай болды?", options: ["Қытай империясының шақыруы", "Соғды еліндегі тап күресінің өршуі", "Түргештердің соғысты тоқтатуы", "Қарлұқтардың қысымы"], correct: 1 },
{ q: "Соғды диқандары мен көпестері не себепті Жетісуга көшіп кетті?", options: ["Сауда жолдарын кеңейту үшін ғана", "Түргештерден қорғану үшін", "Билеушілердің қысымына шыдамағандықтан", "Қытай әскеріне қосылу үшін"], correct: 2 },
{ q: "Соғдылардың Жетісуга қоныс аударуының үшінші себебі неге байланысты болды?", options: ["Арабтардың Орталық Азияны жаулап алу әрекетіне", "Қытайлардың Жетісуды басып алуына", "Түргештердің әлсіреуіне", "Қарлұқтардың көшуіне"], correct: 0 },
{ q: "Соғдылардың Жетісуга қоныс аударуы қай салалардың дамуына елеулі із қалдырды?", options: ["Әскери өнер мен теңіз саудасына", "Егіншілік және қала мәдениетіне", "Мал шаруашылығы мен аңшылыққа", "Кеме жасау мен балық аулауға"], correct: 1 },
{ q: "Жетісуга қоныс аударған соғдылардың кейінгі тағдыры қалай сипатталады?", options: ["Қытайланып кетті", "Арабтанып кетті", "Түркіленіп кетті", "Үнділеніп кетті"], correct: 2 },
{ q: "Соғдылар Жетісуга қай ғасырларда қоныс аударды?", options: ["IV–V ғасырларда", "V–VI ғасырларда", "VI–VIII ғасырларда", "VIII–IX ғасырларда"], correct: 2 },
{ q: "Соғдылар түркі тілді ортаға түскеннен кейін нені қабылдады?", options: ["Қытай тілін және мәдениетін", "Жергілікті тұрғындардың тілін, мәдениеті мен әдет-ғұрпын", "Арабтардың діни дәстүрін", "Парсылардың әскери жүйесін"], correct: 1 },
{ q: "Махмұд Қашғари соғдылар туралы қандай пікір жазған?", options: ["Соғдылардың барлығы араб тілінде сөйлегенін", "Соғдылардың түркі тілін қабылдамағанын", "Соғдылар арасында түркіше сөйлемейтіндердің болмағанын", "Соғдылардың Жетісудан көшіп кеткенін"], correct: 2 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>

396
turik-kaganaty.html Normal file
View File

@ -0,0 +1,396 @@
<!-- no-design-system -->
<!DOCTYPE html>
<html lang="kk" data-theme="auto">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ҰБТ: Түрік қағанаты</title>
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🐺</text></svg>">
<style>
.kt-ai-hero { background: linear-gradient(135deg, var(--kt-ai-bg-soft) 0%, var(--kt-ai-bg) 100%); }
.question-card { margin-bottom: var(--kt-ai-space-6); }
.options-grid { display: grid; gap: var(--kt-ai-space-3); margin-top: var(--kt-ai-space-5); }
.option-btn { text-align: left; justify-content: flex-start; padding-left: var(--kt-ai-space-4); }
.option-btn::before { content: ''; width: 24px; height: 24px; border-radius: 50%; border: 2px solid var(--kt-ai-fg-muted); margin-right: var(--kt-ai-space-3); flex-shrink: 0; display: inline-block; vertical-align: middle; }
.option-btn[data-selected="true"]::before { background: var(--kt-ai-primary); border-color: var(--kt-ai-primary); }
.option-btn.correct { background: #dcfce7 !important; border-color: #22c55e !important; color: #166534; }
.option-btn.wrong { background: #fee2e2 !important; border-color: #ef4444 !important; color: #991b1b; }
.score-display { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); margin: var(--kt-ai-space-6) 0; }
.progress-bar { height: 8px; background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); overflow: hidden; margin-bottom: var(--kt-ai-space-5); }
.progress-fill { height: 100%; background: var(--kt-ai-primary); transition: width 0.3s ease; }
.hidden { display: none; }
.fade-in { animation: fadeIn 0.4s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.timer-badge { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-semibold); }
.timer-badge.warning { background: #fef3c7; color: #92400e; }
.timer-badge.danger { background: #fee2e2; color: #991b1b; }
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--kt-ai-space-4); margin-bottom: var(--kt-ai-space-6); }
.stat-card { text-align: center; padding: var(--kt-ai-space-4); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-xl); }
.stat-value { font-size: var(--kt-ai-text-2xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); }
.welcome-text { font-size: var(--kt-ai-text-lg); color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-3); }
.name-input { max-width: 400px; margin: var(--kt-ai-space-6) auto; }
.answer-feedback { margin-top: var(--kt-ai-space-4); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); font-weight: var(--kt-ai-weight-medium); }
.answer-feedback.correct { background: #dcfce7; color: #166534; }
.answer-feedback.wrong { background: #fee2e2; color: #991b1b; }
</style>
</head>
<body>
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<strong>🇰🇿 ҰБТ: Қазақстан тарихы</strong>
<span class="kt-ai-spacer"></span>
<span id="header-user-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-semibold);"></span>
<span class="kt-ai-spacer"></span>
<a class="kt-ai-btn" data-variant="ghost" href="index.html">Басқа тест</a>
<button class="kt-ai-btn" data-variant="ghost" onclick="showStartScreen()">Қайта бастау</button>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>Түрік қағанаты</h1>
<p class="kt-ai-hero-sub">Біліміңді тексер және қайталауды ұмытпа!</p>
<div id="login-section" style="max-width: 400px; margin: var(--kt-ai-space-6) auto;">
<div class="kt-ai-field">
<label>Аты-жөніңізді енгізіңіз:</label>
<input class="kt-ai-input" id="user-name" placeholder="Мысалы: Алиев Арман" type="text">
</div>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()" style="margin-top: var(--kt-ai-space-4);">Тестілеуді бастау</button>
</div>
<div id="welcome-section" class="hidden">
<p class="welcome-text">Қош келдіңіз, <strong id="user-display-name" style="color: var(--kt-ai-primary); font-weight: var(--kt-ai-weight-bold);"></strong>!</p>
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="startQuiz()">Тестілеуді бастау</button>
</div>
</div>
</section>
<section id="quiz-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4);">
<div class="timer-badge" id="timer">
⏱️ <span id="timer-value">00:00</span>
</div>
<div style="color: var(--kt-ai-fg-muted);">Сұрақ <span id="q-current">1</span> / <span id="q-total">40</span></div>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progress"></div>
</div>
<div class="kt-ai-card question-card fade-in">
<h2 id="question-text" style="margin-bottom: var(--kt-ai-space-5); font-size: var(--kt-ai-text-xl);">Сұрақ мәтіні</h2>
<div class="options-grid" id="options-container"></div>
<div id="answer-feedback" class="answer-feedback hidden"></div>
</div>
<div style="display: flex; gap: var(--kt-ai-space-3); justify-content: space-between; margin-top: var(--kt-ai-space-6);">
<button class="kt-ai-btn" data-variant="ghost" id="prev-btn" onclick="prevQuestion()">← Артқа</button>
<button class="kt-ai-btn" data-variant="primary" id="next-btn" onclick="nextQuestion()">Алға →</button>
</div>
</div>
</section>
<section id="result-section" class="kt-ai-section hidden">
<div class="kt-ai-wrap" data-width="narrow">
<div class="kt-ai-card" style="text-align: center">
<h2>Тестілеу аяқталды!</h2>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value" id="correct-count">0</div>
<div class="stat-label">Дұрыс жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="wrong-count">0</div>
<div class="stat-label">Қате жауап</div>
</div>
<div class="stat-card">
<div class="stat-value" id="percentage">0%</div>
<div class="stat-label">Нәтиже</div>
</div>
</div>
<div class="score-display" id="score">0 / 40</div>
<p id="score-message" style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6); font-size: var(--kt-ai-text-lg);"></p>
<div class="kt-ai-hero-actions">
<button class="kt-ai-btn" data-variant="primary" data-size="lg" onclick="showStartScreen()">Қайта тапсыру</button>
<a class="kt-ai-btn" data-variant="ghost" data-size="lg" href="index.html" style="margin-left: var(--kt-ai-space-3);">Басқа тест</a>
</div>
</div>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>ҰБТ 2027 жыл | Айбек Бахытжанұлы</span>
<span class="kt-ai-spacer"></span>
<span>Сәттілік тілейміз!</span>
</footer>
<script>
const QUESTIONS = [
{ q: "Қазақстан тарихында VI–IX ғасырларды қамтитын кезең қалай аталады?", options: ["Ежелгі дәуір", "Ерте орта ғасыр", "Дамыған орта ғасыр", "Кейінгі орта ғасыр"], correct: 1 },
{ q: "Қазақстан тарихында X–XII ғасырларды қамтитын кезең:", options: ["Ерте орта ғасыр", "Кейінгі орта ғасыр", "Дамыған орта ғасыр", "Ежелгі дәуір"], correct: 2 },
{ q: "Қазақстан тарихында XIII–XVII ғасырларды қамтитын кезең:", options: ["Кейінгі орта ғасыр", "Ерте орта ғасыр", "Дамыған орта ғасыр", "Түркі дәуірі"], correct: 0 },
{ q: "Ежелгі түріктер тарих сахнасына қай кезеңде шықты?", options: ["V ғасырдың басында", "V ғасырдың соңында", "VI ғасырдың ортасында", "VII ғасырдың басында"], correct: 2 },
{ q: "Түркілердің түпкі Отаны қай аймақ болды?", options: ["Алтайдың шығыс бөлігі", "Маньчжурияның батысы", "Солтүстік Кавказ", "Жетісу"], correct: 0 },
{ q: "Түркі дәуірі қай ғасырлар аралығын қамтиды?", options: ["V–X ғасырлар", "VI–XIII ғасырлар", "VII–XIV ғасырлар", "VI–X ғасырлар"], correct: 1 },
{ q: "VI ғасырда Гоби шөлінің солтүстігін мекендеген түркі тілдес тайпалар:", options: ["Қарлұқтар", "Қыпшақтар", "Теле тайпалары", "Оғыздар"], correct: 2 },
{ q: "Теле тайпаларының Гоби шөлінің солтүстігінде мекендегені туралы мәлімет қай дереккөздерде кездеседі?", options: ["Парсы деректерінде", "Араб деректерінде", "Византия деректерінде", "Қытай деректерінде"], correct: 3 },
{ q: "Теле тайпаларының оңтүстік-батысындағы көршілері:", options: ["Иран тілдес тайпалар", "Қытайлар", "Соғдылар", "Византиялықтар"], correct: 0 },
{ q: "Теле тайпаларының оңтүстігіндегі көршісі:", options: ["Парсы елі", "Қытай", "Византия", "Эфталиттер"], correct: 1 },
{ q: "Теле тайпаларының ата-бабалары кімдер болды?", options: ["Сақтар", "Ғұндар", "Үйсіндер", "Қаңлылар"], correct: 1 },
{ q: "Ерте орта ғасырда Қазақстан жерінде ірге тіккен алғашқы феодалдық мемлекеттердің бірі:", options: ["Қарахан мемлекеті", "Түрік қағанаты", "Алтын Орда", "Ақ Орда"], correct: 1 },
{ q: "Түрік қағанаты қай жылы құрылды?", options: ["542 жылы", "545 жылы", "552 жылы", "603 жылы"], correct: 2 },
{ q: "Қытай деректерінде түркілер туралы алғашқы мәліметтер қай жылдан бастап кездеседі?", options: ["542 жылдан", "545 жылдан", "552 жылдан", "568 жылдан"], correct: 0 },
{ q: "Түркілер жужан қағанына салықты қандай түрде төледі?", options: ["Мал түрінде", "Астық түрінде", "Алтын түрінде", "Темір түрінде"], correct: 3 },
{ q: "«Түрік» сөзі қандай мағынаны білдіреді?", options: ["Еркін, тәуелсіз", "Берік, күшті", "Ұлы, даңқты", "Батыл, ержүрек"], correct: 1 },
{ q: "«Түрік» атауы қай әулетке байланысты айтылды?", options: ["Ашина әулетіне", "Жужан әулетіне", "Қытай әулетіне", "Эфталиттер әулетіне"], correct: 0 },
{ q: "Түрік қағанаты негізінен қандай тайпалардан тұрды?", options: ["Оғыздардан", "Қыпшақтардан", "Теле тайпаларынан", "Қарлұқтардан"], correct: 2 },
{ q: "Түрік қолбасшысына Қытай елшісі қай жылы келді?", options: ["542 жылы", "545 жылы", "552 жылы", "568 жылы"], correct: 1 },
{ q: "552 жылы қандай маңызды оқиға болды?", options: ["Түрік қағанаты екіге бөлінді", "Византиямен келісім жасалды", "Бумын жужандар әскерін талқандады", "Эфталиттер мемлекеті құрылды"], correct: 2 },
{ q: "552 жылы Бумын қандай лауазымға ие болды?", options: ["Ябғу", "Шад", "Елбасы", "Түркі елінің қағаны"], correct: 3 },
{ q: "Бумын қаған қай жылы «Елхан» атағын алды?", options: ["545 жылы", "552 жылы", "553 жылы", "603 жылы"], correct: 1 },
{ q: "Бумын қаған қайтыс болғаннан кейін билікке келген тұлға:", options: ["Иштеми қаған", "Земарх", "Мұқан қаған", "Маниах"], correct: 2 },
{ q: "Мұқан қағанның билік құрған жылдары:", options: ["542–552 жылдар", "552–553 жылдар", "553–572 жылдар", "572–603 жылдар"], correct: 2 },
{ q: "Мұқан қаған Бумын қағанға кім болды?", options: ["Інісі", "Баласы", "Әкесі", "Немересі"], correct: 1 },
{ q: "Мұқан қағанның басты жетістіктерінің бірі:", options: ["Византияны жаулап алуы", "Қытайды толық бағындыруы", "Түркілердің Орталық Азия мен Оңтүстік Сібірдегі үстемдігін бекітуі", "Түрік қағанатын Батыс және Шығыс қағанаттарына бөлуі"], correct: 2 },
{ q: "Мұқан қағаннан кейін мемлекетті кім басқарды?", options: ["Бумын", "Иштеми", "Земарх", "Маниах"], correct: 1 },
{ q: "Иштеми қаған Бумынға кім болды?", options: ["Баласы", "Немересі", "Інісі", "Әкесі"], correct: 2 },
{ q: "Иштеми қаған тұсында Түрік қағанатының аумағы қай жерлерге дейін жетті?", options: ["Үндістаннан Қытайға дейін", "Маньчжуриядан Босфорға дейін", "Алтайдан Үндістанға дейін", "Еділден Қытайға дейін"], correct: 1 },
{ q: "Түркілер мен парсылар одақтасып қай мемлекетті талқандады?", options: ["Қытай мемлекетін", "Византияны", "Жужандар мемлекетін", "Эфталиттер мемлекетін"], correct: 3 },
{ q: "568 жылы түрік елшілігін Византияға кім басқарды?", options: ["Земарх", "Маниах", "Мұқан", "Иштеми"], correct: 1 },
{ q: "Византиядан Түрік қағанатына келген елші:", options: ["Маниах", "Бумын", "Земарх", "Ашина"], correct: 2 },
{ q: "Түрік қағанаты қай жылы Батыс Түрік және Шығыс Түрік қағанаттарына бөлінді?", options: ["552 жылы", "568 жылы", "603 жылы", "630 жылы"], correct: 2 },
{ q: "Түрік мемлекетінде қарапайым халық қалай аталды?", options: ["Бектер", "Таттар", "Будындар", "Ябғулар"], correct: 2 },
{ q: "Түрік мемлекетіндегі алым-салық төлеушілер немесе құлдар қалай аталды?", options: ["Будындар", "Бектер", "Таттар", "Ерлер"], correct: 2 },
{ q: "Түрік қағанатының Ұлы қаған ордасы қай жерде орналасты?", options: ["Жетісуда", "Алтайда", "Маньчжурияда", "Солтүстік Кавказда"], correct: 1 },
{ q: "Түрік қағанатында қағанның негізгі міндеттерінің бірі:", options: ["Тек салық жинау", "Тек саудамен айналысу", "Жоғарғы сот міндетін атқарып, әскерге басшылық ету", "Діни рәсімдерді басқару"], correct: 2 },
{ q: "Қағанның мемлекетті басқаруда сүйенген әлеуметтік тобы:", options: ["Қарапайым малшыларға", "Қытай елшілеріне", "Тайпаның ақсүйек қауымына", "Құлдарға"], correct: 2 },
{ q: "Қағанның туысқандары қатарында болған лауазымдарды анықтаңыз.", options: ["Би, болыс, сұлтан", "Ябғу, шад, елтебер", "Уәзір, әмір, қазы", "Тархан, бек, хан"], correct: 1 },
{ q: "Соғыста ерлік көрсеткен жауынгерге берілген атақ:", options: ["Шад", "Ябғу", "Ер", "Елтебер"], correct: 2 }
];
let currentQuestion = 0;
let answers = {};
let quizStarted = false;
let timerInterval = null;
let seconds = 0;
let userName = '';
let answered = false;
let shuffledQuestions = [];
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
function checkLogin() {
const savedName = localStorage.getItem('ebtUserName');
if (savedName) {
userName = savedName;
document.getElementById('login-section').classList.add('hidden');
document.getElementById('welcome-section').classList.remove('hidden');
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
}
function showStartScreen() {
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.querySelector('.kt-ai-hero').classList.remove('hidden');
quizStarted = false;
stopTimer();
checkLogin();
}
function startTimer() {
seconds = 0;
timerInterval = setInterval(() => {
seconds++;
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
document.getElementById('timer-value').textContent =
(mins < 10 ? '0' : '') + mins + ':' + (secs < 10 ? '0' : '') + secs;
const badge = document.getElementById('timer');
if (seconds > 600) {
badge.className = 'timer-badge danger';
} else if (seconds > 300) {
badge.className = 'timer-badge warning';
}
}, 1000);
}
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
document.getElementById('timer').className = 'timer-badge';
}
function startQuiz() {
const nameInput = document.getElementById('user-name');
if (nameInput && nameInput.value.trim()) {
userName = nameInput.value.trim();
localStorage.setItem('ebtUserName', userName);
document.getElementById('user-display-name').textContent = userName;
document.getElementById('header-user-name').textContent = userName;
}
if (!userName) {
alert('Аты-жөніңізді енгізіңіз!');
return;
}
document.querySelector('.kt-ai-hero').classList.add('hidden');
document.getElementById('result-section').classList.add('hidden');
document.getElementById('quiz-section').classList.remove('hidden');
quizStarted = true;
currentQuestion = 0;
answers = {};
seconds = 0;
shuffledQuestions = shuffleArray(QUESTIONS);
startTimer();
document.getElementById('q-total').textContent = shuffledQuestions.length;
showQuestion();
}
function showQuestion() {
const q = shuffledQuestions[currentQuestion];
document.getElementById('q-current').textContent = currentQuestion + 1;
document.getElementById('question-text').textContent = q.q;
const container = document.getElementById('options-container');
container.innerHTML = '';
const feedback = document.getElementById('answer-feedback');
feedback.className = 'answer-feedback hidden';
answered = answers[currentQuestion] !== undefined;
const letters = ['A', 'B', 'C', 'D'];
q.options.forEach((opt, i) => {
const btn = document.createElement('button');
btn.className = 'kt-ai-btn option-btn';
btn.setAttribute('data-selected', answers[currentQuestion] === i);
btn.innerHTML = `<span style="font-weight: bold; margin-right: 8px;">${letters[i]})</span> ${opt}`;
btn.onclick = () => selectAnswer(i);
if (answered) {
btn.disabled = true;
if (i === q.correct) {
btn.classList.add('correct');
} else if (answers[currentQuestion] === i && i !== q.correct) {
btn.classList.add('wrong');
}
} else {
if (answers[currentQuestion] === i) {
btn.style.borderColor = 'var(--kt-ai-primary)';
btn.style.background = 'var(--kt-ai-bg-soft)';
} else {
btn.style.borderColor = 'var(--kt-ai-border)';
btn.style.background = 'var(--kt-ai-card-bg)';
}
}
container.appendChild(btn);
});
if (answered) {
const isCorrect = answers[currentQuestion] === q.correct;
feedback.textContent = isCorrect ? '✅ Дұрыс!' : '❌ Қате! Дұрыс жауап: ' + letters[q.correct] + ') ' + q.options[q.correct];
feedback.className = 'answer-feedback ' + (isCorrect ? 'correct' : 'wrong');
feedback.classList.remove('hidden');
}
updateProgress();
updateButtons();
}
function selectAnswer(index) {
if (answered) return;
answers[currentQuestion] = index;
showQuestion();
}
function nextQuestion() {
if (currentQuestion < QUESTIONS.length - 1) {
currentQuestion++;
showQuestion();
} else {
showResults();
}
}
function prevQuestion() {
if (currentQuestion > 0) {
currentQuestion--;
answered = false;
showQuestion();
}
}
function updateProgress() {
const progress = ((currentQuestion + 1) / QUESTIONS.length) * 100;
document.getElementById('progress').style.width = progress + '%';
}
function updateButtons() {
document.getElementById('prev-btn').style.visibility = currentQuestion === 0 ? 'hidden' : 'visible';
const nextBtn = document.getElementById('next-btn');
nextBtn.textContent = currentQuestion === QUESTIONS.length - 1 ? 'Аяқтау' : 'Алға →';
}
function showResults() {
stopTimer();
let correct = 0;
let wrong = 0;
shuffledQuestions.forEach((q, i) => {
if (answers[i] === q.correct) {
correct++;
} else {
wrong++;
}
});
const percentage = Math.round((correct / shuffledQuestions.length) * 100);
document.getElementById('quiz-section').classList.add('hidden');
document.getElementById('result-section').classList.remove('hidden');
document.getElementById('correct-count').textContent = correct;
document.getElementById('wrong-count').textContent = wrong;
document.getElementById('percentage').textContent = percentage + '%';
document.getElementById('score').textContent = `${correct} / ${QUESTIONS.length}`;
let message = '';
if (percentage >= 90) message = 'Өте жақсы! ҰБТ-ға дайынсың 🎉';
else if (percentage >= 70) message = 'Жақсы нәтиже! 👍';
else if (percentage >= 50) message = 'Жаман емес, бірақ жақсартуға болады 👌';
else message = 'Әлі де дайындалу керек 📚';
document.getElementById('score-message').textContent = message + ' | Уақыт: ' + document.getElementById('timer-value').textContent;
}
document.addEventListener('keydown', (e) => {
if (!quizStarted) return;
if (e.key === 'ArrowRight' || e.key === ' ') nextQuestion();
if (e.key === 'ArrowLeft') prevQuestion();
});
checkLogin();
</script>
</body>
</html>