init
This commit is contained in:
22
favicon.svg
Normal file
22
favicon.svg
Normal file
@@ -0,0 +1,22 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<!-- Градиентный фон -->
|
||||
<defs>
|
||||
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#667eea" />
|
||||
<stop offset="100%" stop-color="#764ba2" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Круглый фон с градиентом -->
|
||||
<circle cx="50" cy="50" r="45" fill="url(#gradient)" />
|
||||
|
||||
<!-- Абстрактный узор в центре -->
|
||||
<path d="M50 30 L65 50 L50 70 L35 50 Z" fill="white" opacity="0.9" />
|
||||
<circle cx="50" cy="50" r="15" fill="none" stroke="white" stroke-width="3" opacity="0.8" />
|
||||
|
||||
<!-- Декоративные точки -->
|
||||
<circle cx="30" cy="30" r="4" fill="white" opacity="0.7" />
|
||||
<circle cx="70" cy="30" r="3" fill="white" opacity="0.7" />
|
||||
<circle cx="70" cy="70" r="4" fill="white" opacity="0.7" />
|
||||
<circle cx="30" cy="70" r="3" fill="white" opacity="0.7" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 964 B |
226
index.html
Normal file
226
index.html
Normal file
@@ -0,0 +1,226 @@
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Тестирование по мультимедиа</title>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
|
||||
/>
|
||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<h1>
|
||||
<i class="fas fa-question-circle"></i> Тестирование по мультимедиа
|
||||
</h1>
|
||||
<p class="subtitle">
|
||||
Проверьте свои знания в области мультимедийных технологий
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div class="quiz-container" id="quiz-container">
|
||||
<div class="start-screen" id="start-screen">
|
||||
<div class="start-content">
|
||||
<h2>Инструкция к тесту</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<i class="fas fa-check-circle"></i> Всего 30 вопросов по теме
|
||||
мультимедиа
|
||||
</li>
|
||||
<li>
|
||||
<i class="fas fa-random"></i> Вопросы и варианты ответов
|
||||
перемешиваются
|
||||
</li>
|
||||
<li>
|
||||
<i class="fas fa-clock"></i> На прохождение теста нет
|
||||
ограничений по времени
|
||||
</li>
|
||||
<li>
|
||||
<i class="fas fa-check-double"></i> Можно выбирать несколько
|
||||
вариантов ответа
|
||||
</li>
|
||||
<li>
|
||||
<i class="fas fa-arrow-right"></i> Проверка происходит при
|
||||
нажатии "Следующий"
|
||||
</li>
|
||||
<li>
|
||||
<i class="fas fa-star"></i> Полный балл за вопрос - если выбраны
|
||||
все правильные ответы
|
||||
</li>
|
||||
<li>
|
||||
<i class="fas fa-chart-bar"></i> Результат будет показан после
|
||||
завершения теста
|
||||
</li>
|
||||
</ul>
|
||||
<button id="start-btn" class="btn start-btn">
|
||||
<i class="fas fa-play"></i> Начать тест
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="quiz-screen hidden" id="quiz-screen">
|
||||
<div class="progress-container">
|
||||
<div class="progress-bar" id="progress-bar"></div>
|
||||
<div class="progress-text" id="progress-text">Вопрос 0 из 0</div>
|
||||
</div>
|
||||
|
||||
<div class="question-container">
|
||||
<div class="question-header">
|
||||
<h2 id="question">Текст вопроса появится здесь</h2>
|
||||
<div class="selection-info" id="selection-info">
|
||||
<i class="fas fa-mouse-pointer"></i> Выбрано:
|
||||
<span id="selected-count">0</span> из
|
||||
<span id="total-options">0</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Блок обратной связи -->
|
||||
<div class="feedback-container hidden" id="feedback-container">
|
||||
<div class="feedback correct-feedback" id="correct-feedback">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
<div class="feedback-content">
|
||||
<span class="feedback-title"
|
||||
>Правильно! Отличная работа!</span
|
||||
>
|
||||
<span class="feedback-detail"
|
||||
>Вы выбрали все правильные ответы</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="feedback partially-feedback" id="partially-feedback">
|
||||
<i class="fas fa-exclamation-circle"></i>
|
||||
<div class="feedback-content">
|
||||
<span class="feedback-title">Частично правильно</span>
|
||||
<span class="feedback-detail"
|
||||
>Вы выбрали <span id="partial-correct-count">0</span> из
|
||||
<span id="total-correct-count">0</span> правильных
|
||||
ответов</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="feedback incorrect-feedback" id="incorrect-feedback">
|
||||
<i class="fas fa-times-circle"></i>
|
||||
<div class="feedback-content">
|
||||
<span class="feedback-title">Неправильно</span>
|
||||
<span class="feedback-detail"
|
||||
>Правильные ответы: <span id="correct-answers-text"></span
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="options-container" id="options-container">
|
||||
<!-- Варианты ответов будут здесь -->
|
||||
</div>
|
||||
|
||||
<div class="question-hint">
|
||||
<i class="fas fa-info-circle"></i> Выберите один или несколько
|
||||
вариантов ответа
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="navigation">
|
||||
<button id="prev-btn" class="btn prev-btn" disabled>
|
||||
<i class="fas fa-arrow-left"></i> Предыдущий
|
||||
</button>
|
||||
<button id="check-btn" class="btn check-btn">
|
||||
<i class="fas fa-check"></i> Проверить и продолжить
|
||||
</button>
|
||||
<button id="next-btn" class="btn next-btn hidden">
|
||||
Следующий <i class="fas fa-arrow-right"></i>
|
||||
</button>
|
||||
<button id="submit-btn" class="btn submit-btn hidden">
|
||||
<i class="fas fa-paper-plane"></i> Завершить тест
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="result-screen hidden" id="result-screen">
|
||||
<div class="result-content">
|
||||
<h2>Результаты тестирования</h2>
|
||||
<div class="score-circle">
|
||||
<div class="circle">
|
||||
<span id="score">0</span>
|
||||
<div class="score-label">из 30</div>
|
||||
</div>
|
||||
<div class="percentage" id="percentage">0%</div>
|
||||
</div>
|
||||
|
||||
<div class="result-details">
|
||||
<div class="result-item correct">
|
||||
<i class="fas fa-check"></i>
|
||||
<span
|
||||
>Правильные ответы:
|
||||
<strong id="correct-count">0</strong></span
|
||||
>
|
||||
</div>
|
||||
<div class="result-item partially">
|
||||
<i class="fas fa-exclamation"></i>
|
||||
<span
|
||||
>Частично правильные:
|
||||
<strong id="partial-count">0</strong></span
|
||||
>
|
||||
</div>
|
||||
<div class="result-item incorrect">
|
||||
<i class="fas fa-times"></i>
|
||||
<span
|
||||
>Неправильные ответы:
|
||||
<strong id="incorrect-count">0</strong></span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="result-actions">
|
||||
<button id="restart-btn" class="btn restart-btn">
|
||||
<i class="fas fa-redo"></i> Пройти тест снова
|
||||
</button>
|
||||
<button id="review-btn" class="btn review-btn">
|
||||
<i class="fas fa-eye"></i> Просмотреть ответы
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="review-screen hidden" id="review-screen">
|
||||
<div class="review-header">
|
||||
<h2>Просмотр ответов</h2>
|
||||
<p>
|
||||
<span class="correct-badge"
|
||||
><i class="fas fa-check"></i> Зеленый</span
|
||||
>
|
||||
- правильные ответы,
|
||||
<span class="partial-badge"
|
||||
><i class="fas fa-exclamation"></i> Желтый</span
|
||||
>
|
||||
- выбранные вами ответы,
|
||||
<span class="incorrect-badge"
|
||||
><i class="fas fa-times"></i> Красный</span
|
||||
>
|
||||
- неправильные выбранные ответы
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="review-container" id="review-container">
|
||||
<!-- Обзор вопросов будет здесь -->
|
||||
</div>
|
||||
|
||||
<div class="review-actions">
|
||||
<button id="back-to-results-btn" class="btn">
|
||||
<i class="fas fa-arrow-left"></i> Назад к результатам
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>Гарантия верности ответов не даётся!</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
332
questions.json
Normal file
332
questions.json
Normal file
@@ -0,0 +1,332 @@
|
||||
[
|
||||
{
|
||||
"text": "Составляющие мультимедиа могут быть разбиты на основные группы?",
|
||||
"options": [
|
||||
{
|
||||
"text": "Текстовая, визуальная и звуковая информация.",
|
||||
"correct": true
|
||||
},
|
||||
{
|
||||
"text": "Текстовая, визуальная, звуковая информация и данные.",
|
||||
"correct": false
|
||||
},
|
||||
{
|
||||
"text": "Текстовая, визуальная, звуковая информация, данные и графическая информация.",
|
||||
"correct": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "С точки зрения передачи мультимедиа могут быть классифицированы на?",
|
||||
"options": [
|
||||
{ "text": "Передаваемые в реальном времени.", "correct": true },
|
||||
{ "text": "Передаваемые в on-line.", "correct": false },
|
||||
{ "text": "Передаваемые в не реальном времени.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Самый популярный тип мультимедиа?",
|
||||
"options": [
|
||||
{ "text": "Видео.", "correct": false },
|
||||
{ "text": "Звук.", "correct": false },
|
||||
{ "text": "Текст.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Прогрессивное сжатие достигается?",
|
||||
"options": [
|
||||
{ "text": "Прогрессивным кодированием.", "correct": true },
|
||||
{ "text": "Векторной квантизацией.", "correct": true },
|
||||
{ "text": "Пирамидальным кодированием.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "В Интернет-телефонии человек может спокойно относиться к задержкам не более?",
|
||||
"options": [
|
||||
{ "text": "200 мс.", "correct": true },
|
||||
{ "text": "250 мс.", "correct": false },
|
||||
{ "text": "300 мс.", "correct": false }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Управление сессиями включает?",
|
||||
"options": [
|
||||
{ "text": "Запрос на сессию, удаление сессии.", "correct": false },
|
||||
{
|
||||
"text": "Описание типа мультимедиа, оповещение о сессии.",
|
||||
"correct": true
|
||||
},
|
||||
{ "text": "Идентификация сессии, управление сессией.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Задержка при передаче пакетов зависит от следующих факторов?",
|
||||
"options": [
|
||||
{
|
||||
"text": "Число активных сессий, пропускная способность канала.",
|
||||
"correct": true
|
||||
},
|
||||
{
|
||||
"text": "Задержки маршрутизации, задержка при обработки очередей.",
|
||||
"correct": true
|
||||
},
|
||||
{
|
||||
"text": "MAC задержка, переключатель контекста в ОС.",
|
||||
"correct": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Многие приложения используют при передаче протокол UDP, в котором нет механизмов контроля перегрузок и есть тенденция к полной остановке передачи от перегрузок канала, данная проблема решается с помощью?",
|
||||
"options": [
|
||||
{ "text": "Управления доступом.", "correct": true },
|
||||
{ "text": "Резервированием пропускной способности.", "correct": true },
|
||||
{ "text": "Механизмами управления трафиком.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Пропускная способность определяет?",
|
||||
"options": [
|
||||
{
|
||||
"text": "Постоянно увеличивающуюся разницу между заданным и фактическим моментом появления мультимедийных объектов потока.",
|
||||
"correct": false
|
||||
},
|
||||
{ "text": "Сколько данных может быть передано в сети.", "correct": true },
|
||||
{
|
||||
"text": "Максимальную задержку передачи данных от отправителя до получателя.",
|
||||
"correct": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Задержка определяет?",
|
||||
"options": [
|
||||
{
|
||||
"text": "Постоянно увеличивающуюся разницу между заданным и фактическим моментом появления мультимедийных объектов потока.",
|
||||
"correct": false
|
||||
},
|
||||
{
|
||||
"text": "Сколько данных может быть передано в сети.",
|
||||
"correct": false
|
||||
},
|
||||
{
|
||||
"text": "Максимальную задержку передачи данных от отправителя до получателя.",
|
||||
"correct": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Сдвиг определяет?",
|
||||
"options": [
|
||||
{
|
||||
"text": "Постоянно увеличивающуюся разницу между заданным и фактическим моментом появления мультимедийных объектов потока.",
|
||||
"correct": true
|
||||
},
|
||||
{
|
||||
"text": "Сколько данных может быть передано в сети.",
|
||||
"correct": false
|
||||
},
|
||||
{
|
||||
"text": "Максимальную задержку передачи данных от отправителя до получателя.",
|
||||
"correct": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "При маршрутизации на основе QoS?",
|
||||
"options": [
|
||||
{
|
||||
"text": "Решения о маршрутизации основаны не на знании топологии сети и ее метрик, а на некоторых политиках администрирования.",
|
||||
"correct": false
|
||||
},
|
||||
{
|
||||
"text": "Маршруты вычисляются на основе нескольких ограничений.",
|
||||
"correct": false
|
||||
},
|
||||
{
|
||||
"text": "Пути для разных потоков определяются с учетом некоторой информации о доступности ресурсов сети.",
|
||||
"correct": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Какие классы обслуживания вводит сущность Interserv?",
|
||||
"options": [
|
||||
{ "text": "Классы гарантированного сервиса.", "correct": true },
|
||||
{ "text": "Классы контроля нагрузки.", "correct": true },
|
||||
{ "text": "Классы негарантированной доставки.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "В модели сервиса Интернета - Дифференцированный сервис, каждая вершина в домене может быть?",
|
||||
"options": [
|
||||
{ "text": "Граничной вершиной.", "correct": true },
|
||||
{ "text": "Смежной вершиной.", "correct": false },
|
||||
{ "text": "Внутренней вершиной.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Протоколами, которые были стандартизированы для удовлетворения различных аспектов управления сессиями являются?",
|
||||
"options": [
|
||||
{ "text": "SDP SAP.", "correct": true },
|
||||
{ "text": "RTP, RTCP, RTSP.", "correct": false },
|
||||
{ "text": "HTTP, SMTP.", "correct": false }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "RTP обеспечивает функции?",
|
||||
"options": [
|
||||
{
|
||||
"text": "Установление аутентичности, шифрование данных в пакете IP.",
|
||||
"correct": false
|
||||
},
|
||||
{
|
||||
"text": "Упорядочивание, идентификация передаваемой информации.",
|
||||
"correct": true
|
||||
},
|
||||
{
|
||||
"text": "Индикация фреймов, идентификация источника, синхронизация фрагментов мультимедиа.",
|
||||
"correct": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Стандарт H.323 обеспечивает сервис/сервисы мультимедийных коммуникаций типа?",
|
||||
"options": [
|
||||
{ "text": "Point-to-multipoint.", "correct": true },
|
||||
{ "text": "Point-to-point.", "correct": true },
|
||||
{ "text": "Multipoint-to-multipoint.", "correct": false }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Стандарт H.323 определяет следующие компоненты, которые обеспечивают сервисы мультимедийных коммуникаций?",
|
||||
"options": [
|
||||
{ "text": "Гейткипер, шлюз.", "correct": true },
|
||||
{ "text": "Порталл, мост.", "correct": false },
|
||||
{ "text": "Терминалы, MCU.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Для установки соединения и разъединения между двумя конечными элементами H.323 используется протокол?",
|
||||
"options": [
|
||||
{ "text": "H.245.", "correct": false },
|
||||
{ "text": "H.225.", "correct": false },
|
||||
{ "text": "Q.931.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Для установки соединения в мультимедийной сессии SIP выполняет следующие этапы?",
|
||||
"options": [
|
||||
{
|
||||
"text": "Инициализация сессии, установка соединения, доставка описания сессии, управление активной сессией, завершение сессии.",
|
||||
"correct": false
|
||||
},
|
||||
{
|
||||
"text": "Инициализация сессии, доставка описания сессии, управление активной сессией, завершение сессии.",
|
||||
"correct": true
|
||||
},
|
||||
{
|
||||
"text": "Инициализация сессии, доставка описания сессии, управление активной сессией, контроль за сессией, завершение сессии.",
|
||||
"correct": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Сессия идентифицируется сетевым адресом и парами портов отправления и получения информации. По умолчанию эта пара портов?",
|
||||
"options": [
|
||||
{ "text": "5050 и 5051.", "correct": false },
|
||||
{ "text": "5404 и 5405.", "correct": false },
|
||||
{ "text": "5004 и 5005.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Быстре определение принадлежности пакета к RTP-потоку за счет?",
|
||||
"options": [
|
||||
{ "text": "Проверке сессии RTP.", "correct": false },
|
||||
{ "text": "Пакетной проверке.", "correct": true },
|
||||
{ "text": "Потоковой проверке.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Реализация RTCP включает в себя части?",
|
||||
"options": [
|
||||
{ "text": "Форматы пакетов.", "correct": true },
|
||||
{ "text": "Временные правила.", "correct": true },
|
||||
{ "text": "Базу данных участников.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Спецификация RTCP определяет следующие стандартные форматы пакетов?",
|
||||
"options": [
|
||||
{
|
||||
"text": "Описание источника, формат определяемый приложением, управление участниками.",
|
||||
"correct": true
|
||||
},
|
||||
{ "text": "Служебный, информационный.", "correct": false },
|
||||
{ "text": "Отчет получателя, отчет отправителя.", "correct": true }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Информация о сессии RTCP, на основе которой происходит настройка характеристик сессии по времени, храниться в виде набора переменных?",
|
||||
"options": [
|
||||
{
|
||||
"text": "Пропускная способность, фрагмент пропускной способности, средний размер RTCP-пакетов.",
|
||||
"correct": true
|
||||
},
|
||||
{ "text": "Флаг.", "correct": true },
|
||||
{
|
||||
"text": "Количество участников сессии, время последней отсылки пакетов RTCP, количество переданных RTCP-пакетов и байтов данных, соответствие.",
|
||||
"correct": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "Среднее время ожидания участником очередного пакета RTCP называется?",
|
||||
"options": [
|
||||
{ "text": "Задержкой.", "correct": false },
|
||||
{ "text": "Отчетным интервалом.", "correct": true },
|
||||
{ "text": "Временем ожидания.", "correct": false }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "На среднее время ожидания влияют следующий/следующие фактор/факторы?",
|
||||
"options": [
|
||||
{
|
||||
"text": "Пропускная способность канала, выделенная под RTCP.",
|
||||
"correct": true
|
||||
},
|
||||
{
|
||||
"text": "Средний размер передаваемых и получаемых RTCP-пакетов.",
|
||||
"correct": true
|
||||
},
|
||||
{
|
||||
"text": "Общее количество участников и процент отправителей среди них.",
|
||||
"correct": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "В начале сессии при использовании только базовых правил передачи данных каждый участник будет исходить из отсутствия на данный момент других участников сессии и соответствующим образом структурировать первый пакет RTCP. Он перешлет этот пакет в среднем через половину минимального отчетного интервала и будет строить следующий пакет на основе количества присоединившихся на данный момент участников, которых может быть несколько сотен или даже тысяч. Из-за низкого начального вычисленного количества участников сессии будет наблюдаться резкий рост нагрузки на сеть, что часто приводит к ее перегрузке. Необходимо применить процедуру?",
|
||||
"options": [
|
||||
{ "text": "Процедура пересмотра назад.", "correct": false },
|
||||
{ "text": "Процедура пересмотра вперед.", "correct": true },
|
||||
{ "text": "Процедура пересмотра пакетов BYE.", "correct": false }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "При одновременном отключении большого количества пользователей возникает проблема со слишком большими задержками в отчетах оставшихся участников сессии. Эти задержки могут восприниматься как длительное молчание и пользователи в этом случае отмечаются как неактивные. Проблема решается путем: при получении каждого пакета BYE пересчитывается число участников сессии и время отсылки следующего пакета. В результате изменяется время отсылки пакетов, которое в этом случае уменьшается. Необходимо применить процедуру?",
|
||||
"options": [
|
||||
{ "text": "Процедура пересмотра назад.", "correct": true },
|
||||
{ "text": "Процедура пересмотра вперед.", "correct": false },
|
||||
{ "text": "Процедура пересмотра пакетов BYE.", "correct": false }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "RTP разрешает посылать пакет BYE немедленно только в том случае, если число участников сессии менее?",
|
||||
"options": [
|
||||
{ "text": "25.", "correct": false },
|
||||
{ "text": "30.", "correct": false },
|
||||
{ "text": "50.", "correct": true }
|
||||
]
|
||||
}
|
||||
]
|
||||
499
script.js
Normal file
499
script.js
Normal file
@@ -0,0 +1,499 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Элементы DOM
|
||||
const startScreen = document.getElementById('start-screen');
|
||||
const quizScreen = document.getElementById('quiz-screen');
|
||||
const resultScreen = document.getElementById('result-screen');
|
||||
const reviewScreen = document.getElementById('review-screen');
|
||||
|
||||
const startBtn = document.getElementById('start-btn');
|
||||
const prevBtn = document.getElementById('prev-btn');
|
||||
const checkBtn = document.getElementById('check-btn');
|
||||
const nextBtn = document.getElementById('next-btn');
|
||||
const submitBtn = document.getElementById('submit-btn');
|
||||
const restartBtn = document.getElementById('restart-btn');
|
||||
const reviewBtn = document.getElementById('review-btn');
|
||||
const backToResultsBtn = document.getElementById('back-to-results-btn');
|
||||
|
||||
const questionElement = document.getElementById('question');
|
||||
const optionsContainer = document.getElementById('options-container');
|
||||
const selectionInfo = document.getElementById('selection-info');
|
||||
const selectedCountElement = document.getElementById('selected-count');
|
||||
const totalOptionsElement = document.getElementById('total-options');
|
||||
|
||||
const feedbackContainer = document.getElementById('feedback-container');
|
||||
const correctFeedback = document.getElementById('correct-feedback');
|
||||
const partialFeedback = document.getElementById('partially-feedback');
|
||||
const incorrectFeedback = document.getElementById('incorrect-feedback');
|
||||
const partialCorrectCount = document.getElementById('partial-correct-count');
|
||||
const totalCorrectCount = document.getElementById('total-correct-count');
|
||||
const correctAnswersText = document.getElementById('correct-answers-text');
|
||||
|
||||
const progressBar = document.querySelector('.progress-bar');
|
||||
const progressText = document.getElementById('progress-text');
|
||||
|
||||
const scoreElement = document.getElementById('score');
|
||||
const percentageElement = document.getElementById('percentage');
|
||||
const correctCountElement = document.getElementById('correct-count');
|
||||
const partialCountElement = document.getElementById('partial-count');
|
||||
const incorrectCountElement = document.getElementById('incorrect-count');
|
||||
const reviewContainer = document.getElementById('review-container');
|
||||
|
||||
// Переменные состояния
|
||||
let questions = [];
|
||||
let shuffledQuestions = [];
|
||||
let currentQuestionIndex = 0;
|
||||
let userAnswers = []; // Массив массивов выбранных индексов
|
||||
let questionStatus = []; // Статус ответа на каждый вопрос: 'unanswered', 'correct', 'partial', 'incorrect'
|
||||
let score = 0;
|
||||
let letters = ['а', 'б', 'в', 'г', 'д', 'е'];
|
||||
|
||||
// Загрузка вопросов из JSON
|
||||
async function loadQuestions() {
|
||||
try {
|
||||
const response = await fetch('questions.json');
|
||||
if (!response.ok) {
|
||||
throw new Error('Не удалось загрузить вопросы');
|
||||
}
|
||||
questions = await response.json();
|
||||
console.log('Вопросы загружены:', questions.length);
|
||||
} catch (error) {
|
||||
console.error('Ошибка загрузки вопросов:', error);
|
||||
createDemoQuestions();
|
||||
}
|
||||
}
|
||||
|
||||
// Создание демо-вопросов, если файл не найден
|
||||
function createDemoQuestions() {
|
||||
questions = [
|
||||
{
|
||||
"text": "Составляющие мультимедиа могут быть разбиты на основные группы?",
|
||||
"options": [
|
||||
{ "text": "Текстовая, визуальная и звуковая информация.", "correct": false },
|
||||
{ "text": "Текстовая, визуальная, звуковая информация и данные.", "correct": true },
|
||||
{ "text": "Текстовая, визуальная, звуковая информация, данные и графическая информация.", "correct": false },
|
||||
{ "text": "Только текстовая и визуальная информация.", "correct": false }
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "С точки зрения передачи мультимедиа могут быть классифицированы на?",
|
||||
"options": [
|
||||
{ "text": "Передаваемые в реальном времени.", "correct": true },
|
||||
{ "text": "Передаваемые в on-line.", "correct": false },
|
||||
{ "text": "Передаваемые в не реальном времени.", "correct": true },
|
||||
{ "text": "Только передаваемые по запросу.", "correct": false }
|
||||
]
|
||||
}
|
||||
];
|
||||
console.log('Созданы демо-вопросы с множественным выбором');
|
||||
}
|
||||
|
||||
// Инициализация теста
|
||||
function initializeQuiz() {
|
||||
// Перемешиваем вопросы
|
||||
shuffledQuestions = [...questions];
|
||||
shuffleArray(shuffledQuestions);
|
||||
|
||||
// Перемешиваем варианты ответов в каждом вопросе
|
||||
shuffledQuestions.forEach(question => {
|
||||
shuffleArray(question.options);
|
||||
|
||||
// Находим индексы правильных ответов после перемешивания
|
||||
question.correctOptionIndices = [];
|
||||
question.options.forEach((option, index) => {
|
||||
if (option.correct) {
|
||||
question.correctOptionIndices.push(index);
|
||||
}
|
||||
});
|
||||
|
||||
// Сохраняем текст правильных ответов для отображения
|
||||
question.correctAnswersText = question.correctOptionIndices
|
||||
.map(idx => `${letters[idx]}) ${question.options[idx].text}`)
|
||||
.join('; ');
|
||||
});
|
||||
|
||||
// Инициализируем массивы
|
||||
userAnswers = new Array(shuffledQuestions.length).fill(null).map(() => []);
|
||||
questionStatus = new Array(shuffledQuestions.length).fill('unanswered');
|
||||
|
||||
// Сбрасываем индекс текущего вопроса и счет
|
||||
currentQuestionIndex = 0;
|
||||
score = 0;
|
||||
|
||||
// Обновляем UI
|
||||
updateProgress();
|
||||
showQuestion();
|
||||
}
|
||||
|
||||
// Перемешивание массива (алгоритм Фишера-Йетса)
|
||||
function shuffleArray(array) {
|
||||
for (let i = array.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[array[i], array[j]] = [array[j], array[i]];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
// Показать вопрос
|
||||
function showQuestion() {
|
||||
const question = shuffledQuestions[currentQuestionIndex];
|
||||
questionElement.textContent = `${currentQuestionIndex + 1}. ${question.text}`;
|
||||
|
||||
// Обновляем информацию о выборе
|
||||
totalOptionsElement.textContent = question.options.length;
|
||||
updateSelectionInfo();
|
||||
|
||||
// Скрываем блок обратной связи, если вопрос еще не проверен
|
||||
if (questionStatus[currentQuestionIndex] === 'unanswered') {
|
||||
feedbackContainer.classList.add('hidden');
|
||||
} else {
|
||||
showFeedback();
|
||||
}
|
||||
|
||||
// Очищаем контейнер с вариантами
|
||||
optionsContainer.innerHTML = '';
|
||||
|
||||
// Создаем варианты ответов
|
||||
question.options.forEach((option, index) => {
|
||||
const optionElement = document.createElement('div');
|
||||
optionElement.className = 'option';
|
||||
|
||||
// Проверяем, выбран ли этот вариант
|
||||
const isSelected = userAnswers[currentQuestionIndex].includes(index);
|
||||
const isChecked = questionStatus[currentQuestionIndex] !== 'unanswered';
|
||||
|
||||
if (isSelected) {
|
||||
optionElement.classList.add('selected');
|
||||
}
|
||||
|
||||
// Если вопрос проверен, показываем правильность ответов
|
||||
if (isChecked) {
|
||||
optionElement.classList.add('checked');
|
||||
|
||||
const isCorrectOption = question.correctOptionIndices.includes(index);
|
||||
|
||||
if (isSelected && isCorrectOption) {
|
||||
optionElement.classList.add('correct');
|
||||
} else if (isSelected && !isCorrectOption) {
|
||||
optionElement.classList.add('incorrect');
|
||||
} else if (!isSelected && isCorrectOption) {
|
||||
optionElement.classList.add('correct');
|
||||
}
|
||||
}
|
||||
|
||||
optionElement.innerHTML = `
|
||||
<div class="option-checkbox"></div>
|
||||
<div class="option-text">${letters[index]}) ${option.text}</div>
|
||||
`;
|
||||
|
||||
// Если вопрос еще не проверен, добавляем обработчик клика
|
||||
if (!isChecked) {
|
||||
optionElement.addEventListener('click', () => toggleOption(index));
|
||||
}
|
||||
|
||||
optionsContainer.appendChild(optionElement);
|
||||
});
|
||||
|
||||
// Обновляем состояние кнопок навигации
|
||||
updateNavigationButtons();
|
||||
}
|
||||
|
||||
// Переключить выбор варианта
|
||||
function toggleOption(optionIndex) {
|
||||
const currentAnswers = userAnswers[currentQuestionIndex];
|
||||
const index = currentAnswers.indexOf(optionIndex);
|
||||
|
||||
if (index === -1) {
|
||||
// Добавляем вариант
|
||||
currentAnswers.push(optionIndex);
|
||||
} else {
|
||||
// Удаляем вариант
|
||||
currentAnswers.splice(index, 1);
|
||||
}
|
||||
|
||||
// Обновляем отображение
|
||||
updateSelectionInfo();
|
||||
showQuestion();
|
||||
}
|
||||
|
||||
// Обновить информацию о выбранных вариантах
|
||||
function updateSelectionInfo() {
|
||||
const selectedCount = userAnswers[currentQuestionIndex].length;
|
||||
selectedCountElement.textContent = selectedCount;
|
||||
|
||||
// Подсвечиваем информацию в зависимости от количества выбранных ответов
|
||||
if (selectedCount === 0) {
|
||||
selectionInfo.style.borderColor = '#e0e0e0';
|
||||
selectionInfo.style.backgroundColor = '#f0f4ff';
|
||||
} else {
|
||||
selectionInfo.style.borderColor = '#4a00e0';
|
||||
selectionInfo.style.backgroundColor = '#e6f7ff';
|
||||
}
|
||||
}
|
||||
|
||||
// Обновить кнопки навигации
|
||||
function updateNavigationButtons() {
|
||||
const isAnswered = questionStatus[currentQuestionIndex] !== 'unanswered';
|
||||
const hasSelection = userAnswers[currentQuestionIndex].length > 0;
|
||||
|
||||
prevBtn.disabled = currentQuestionIndex === 0;
|
||||
|
||||
if (isAnswered) {
|
||||
checkBtn.classList.add('hidden');
|
||||
nextBtn.classList.remove('hidden');
|
||||
} else {
|
||||
checkBtn.classList.remove('hidden');
|
||||
nextBtn.classList.add('hidden');
|
||||
checkBtn.disabled = !hasSelection;
|
||||
}
|
||||
|
||||
// Показываем кнопку завершения на последнем проверенном вопросе
|
||||
const allQuestionsAnswered = questionStatus.every(status => status !== 'unanswered');
|
||||
const isLastQuestion = currentQuestionIndex === shuffledQuestions.length - 1;
|
||||
|
||||
if (isLastQuestion && isAnswered) {
|
||||
nextBtn.classList.add('hidden');
|
||||
submitBtn.classList.remove('hidden');
|
||||
} else {
|
||||
submitBtn.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
// Проверить ответ и показать результат
|
||||
function checkAnswer() {
|
||||
const question = shuffledQuestions[currentQuestionIndex];
|
||||
const userSelected = userAnswers[currentQuestionIndex];
|
||||
const correctIndices = question.correctOptionIndices;
|
||||
|
||||
// Находим количество правильных выбранных ответов
|
||||
const correctSelected = userSelected.filter(idx => correctIndices.includes(idx)).length;
|
||||
const incorrectSelected = userSelected.length - correctSelected;
|
||||
const missedCorrect = correctIndices.length - correctSelected;
|
||||
|
||||
// Определяем статус ответа
|
||||
let status;
|
||||
let feedbackType;
|
||||
|
||||
if (incorrectSelected === 0 && missedCorrect === 0) {
|
||||
// Все правильные выбраны, ничего лишнего
|
||||
status = 'correct';
|
||||
feedbackType = 'correct';
|
||||
score += 1;
|
||||
} else if (correctSelected > 0 && (incorrectSelected > 0 || missedCorrect > 0)) {
|
||||
// Частично правильно
|
||||
status = 'partial';
|
||||
feedbackType = 'partial';
|
||||
score += 0.5; // Половина балла за частично правильный ответ
|
||||
} else {
|
||||
// Полностью неправильно
|
||||
status = 'incorrect';
|
||||
feedbackType = 'incorrect';
|
||||
}
|
||||
|
||||
// Сохраняем статус вопроса
|
||||
questionStatus[currentQuestionIndex] = status;
|
||||
|
||||
// Показываем обратную связь
|
||||
showFeedback(correctSelected, correctIndices.length);
|
||||
|
||||
// Обновляем навигацию
|
||||
updateNavigationButtons();
|
||||
|
||||
// Обновляем отображение вариантов
|
||||
showQuestion();
|
||||
}
|
||||
|
||||
// Показать обратную связь
|
||||
function showFeedback(correctSelected = 0, totalCorrect = 0) {
|
||||
const question = shuffledQuestions[currentQuestionIndex];
|
||||
const status = questionStatus[currentQuestionIndex];
|
||||
|
||||
// Скрываем все виды обратной связи
|
||||
correctFeedback.classList.add('hidden');
|
||||
partialFeedback.classList.add('hidden');
|
||||
incorrectFeedback.classList.add('hidden');
|
||||
|
||||
// Показываем соответствующий вид обратной связи
|
||||
switch (status) {
|
||||
case 'correct':
|
||||
correctFeedback.classList.remove('hidden');
|
||||
break;
|
||||
case 'partial':
|
||||
partialFeedback.classList.remove('hidden');
|
||||
partialCorrectCount.textContent = correctSelected;
|
||||
totalCorrectCount.textContent = totalCorrect;
|
||||
break;
|
||||
case 'incorrect':
|
||||
incorrectFeedback.classList.remove('hidden');
|
||||
correctAnswersText.textContent = question.correctAnswersText;
|
||||
break;
|
||||
}
|
||||
|
||||
feedbackContainer.classList.remove('hidden');
|
||||
}
|
||||
|
||||
// Обновление прогресса
|
||||
function updateProgress() {
|
||||
const progress = ((currentQuestionIndex + 1) / shuffledQuestions.length) * 100;
|
||||
progressBar.style.setProperty('--width', `${progress}%`);
|
||||
progressText.textContent = `Вопрос ${currentQuestionIndex + 1} из ${shuffledQuestions.length}`;
|
||||
}
|
||||
|
||||
// Переход к следующему вопросу
|
||||
function nextQuestion() {
|
||||
if (currentQuestionIndex < shuffledQuestions.length - 1) {
|
||||
currentQuestionIndex++;
|
||||
updateProgress();
|
||||
showQuestion();
|
||||
}
|
||||
}
|
||||
|
||||
// Переход к предыдущему вопросу
|
||||
function prevQuestion() {
|
||||
if (currentQuestionIndex > 0) {
|
||||
currentQuestionIndex--;
|
||||
updateProgress();
|
||||
showQuestion();
|
||||
}
|
||||
}
|
||||
|
||||
// Завершение теста и подсчет результатов
|
||||
function finishQuiz() {
|
||||
// Подсчет детальной статистики
|
||||
let correctCount = 0;
|
||||
let partialCount = 0;
|
||||
let incorrectCount = 0;
|
||||
|
||||
questionStatus.forEach(status => {
|
||||
switch (status) {
|
||||
case 'correct':
|
||||
correctCount++;
|
||||
break;
|
||||
case 'partial':
|
||||
partialCount++;
|
||||
break;
|
||||
case 'incorrect':
|
||||
incorrectCount++;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// Обновление экрана результатов
|
||||
scoreElement.textContent = Math.round(score * 10) / 10; // Округляем до одного знака после запятой
|
||||
const percentage = Math.round((score / shuffledQuestions.length) * 100);
|
||||
percentageElement.textContent = `${percentage}%`;
|
||||
correctCountElement.textContent = correctCount;
|
||||
partialCountElement.textContent = partialCount;
|
||||
incorrectCountElement.textContent = incorrectCount;
|
||||
|
||||
// Обновление кругового индикатора
|
||||
const circle = document.querySelector('.circle');
|
||||
circle.style.background = `conic-gradient(#4a00e0 ${percentage}%, #e0e0e0 ${percentage}%)`;
|
||||
|
||||
// Переключение экранов
|
||||
quizScreen.classList.add('hidden');
|
||||
resultScreen.classList.remove('hidden');
|
||||
}
|
||||
|
||||
// Показать обзор ответов
|
||||
function showReview() {
|
||||
reviewContainer.innerHTML = '';
|
||||
|
||||
shuffledQuestions.forEach((question, index) => {
|
||||
const reviewItem = document.createElement('div');
|
||||
reviewItem.className = 'review-item';
|
||||
|
||||
const status = questionStatus[index];
|
||||
const userSelected = userAnswers[index];
|
||||
const correctIndices = question.correctOptionIndices;
|
||||
|
||||
// Определяем статус для отображения
|
||||
let statusText, statusClass;
|
||||
switch (status) {
|
||||
case 'correct':
|
||||
statusText = 'Правильно';
|
||||
statusClass = 'status-correct';
|
||||
break;
|
||||
case 'partial':
|
||||
statusText = 'Частично правильно';
|
||||
statusClass = 'status-partial';
|
||||
break;
|
||||
case 'incorrect':
|
||||
statusText = 'Неправильно';
|
||||
statusClass = 'status-incorrect';
|
||||
break;
|
||||
default:
|
||||
statusText = 'Не отвечено';
|
||||
statusClass = 'status-incorrect';
|
||||
}
|
||||
|
||||
let optionsHTML = '';
|
||||
question.options.forEach((option, optionIndex) => {
|
||||
let optionClass = '';
|
||||
const isCorrect = correctIndices.includes(optionIndex);
|
||||
const isSelected = userSelected.includes(optionIndex);
|
||||
|
||||
if (isCorrect && isSelected) {
|
||||
optionClass = 'user-correct';
|
||||
} else if (isCorrect && !isSelected) {
|
||||
optionClass = 'correct-answer';
|
||||
} else if (!isCorrect && isSelected) {
|
||||
optionClass = 'user-incorrect';
|
||||
} else if (status === 'partial' && isSelected && !isCorrect) {
|
||||
optionClass = 'user-partial';
|
||||
}
|
||||
|
||||
optionsHTML += `
|
||||
<div class="review-option ${optionClass}">
|
||||
<strong>${letters[optionIndex]})</strong> ${option.text}
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
reviewItem.innerHTML = `
|
||||
<div class="review-question">
|
||||
<span>${index + 1}. ${question.text}</span>
|
||||
<span class="question-status ${statusClass}">${statusText}</span>
|
||||
</div>
|
||||
<div class="review-options">
|
||||
${optionsHTML}
|
||||
</div>
|
||||
<div style="margin-top: 15px; font-style: italic;">
|
||||
Ваши ответы: ${userSelected.length > 0
|
||||
? userSelected.map(idx => letters[idx]).join(', ')
|
||||
: 'нет ответа'}
|
||||
</div>
|
||||
`;
|
||||
|
||||
reviewContainer.appendChild(reviewItem);
|
||||
});
|
||||
|
||||
resultScreen.classList.add('hidden');
|
||||
reviewScreen.classList.remove('hidden');
|
||||
}
|
||||
|
||||
// Начало теста
|
||||
function startQuiz() {
|
||||
startScreen.classList.add('hidden');
|
||||
quizScreen.classList.remove('hidden');
|
||||
initializeQuiz();
|
||||
}
|
||||
|
||||
// События
|
||||
startBtn.addEventListener('click', startQuiz);
|
||||
prevBtn.addEventListener('click', prevQuestion);
|
||||
checkBtn.addEventListener('click', checkAnswer);
|
||||
nextBtn.addEventListener('click', nextQuestion);
|
||||
submitBtn.addEventListener('click', finishQuiz);
|
||||
restartBtn.addEventListener('click', () => {
|
||||
resultScreen.classList.add('hidden');
|
||||
startScreen.classList.remove('hidden');
|
||||
});
|
||||
reviewBtn.addEventListener('click', showReview);
|
||||
backToResultsBtn.addEventListener('click', () => {
|
||||
reviewScreen.classList.add('hidden');
|
||||
resultScreen.classList.remove('hidden');
|
||||
});
|
||||
|
||||
// Загружаем вопросы при загрузке страницы
|
||||
loadQuestions();
|
||||
});
|
||||
732
style.css
Normal file
732
style.css
Normal file
@@ -0,0 +1,732 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1000px;
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header {
|
||||
background: linear-gradient(to right, #4a00e0, #8e2de2);
|
||||
color: white;
|
||||
padding: 25px 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 2.2rem;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
header .subtitle {
|
||||
font-size: 1.1rem;
|
||||
opacity: 0.9;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.mode-indicator {
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
border-radius: 10px;
|
||||
padding: 12px 20px;
|
||||
margin-top: 15px;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.mode-tag {
|
||||
background-color: #ff9800;
|
||||
color: white;
|
||||
padding: 5px 15px;
|
||||
border-radius: 20px;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.mode-info {
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.quiz-container {
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.start-screen,
|
||||
.quiz-screen,
|
||||
.result-screen,
|
||||
.review-screen {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.start-content {
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.start-content h2 {
|
||||
color: #333;
|
||||
margin-bottom: 25px;
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.start-content ul {
|
||||
text-align: left;
|
||||
max-width: 700px;
|
||||
margin: 0 auto 30px;
|
||||
background-color: #f8f9fa;
|
||||
padding: 25px;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.start-content li {
|
||||
margin-bottom: 15px;
|
||||
font-size: 1.1rem;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.start-content li i {
|
||||
color: #4a00e0;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background: linear-gradient(to right, #4a00e0, #8e2de2);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 15px 30px;
|
||||
border-radius: 50px;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
box-shadow: 0 5px 15px rgba(74, 0, 224, 0.3);
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 20px rgba(74, 0, 224, 0.4);
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
background: #cccccc;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.check-btn {
|
||||
background: linear-gradient(to right, #ff9800, #ff5722);
|
||||
}
|
||||
|
||||
.check-btn:hover {
|
||||
box-shadow: 0 8px 20px rgba(255, 87, 34, 0.4);
|
||||
}
|
||||
|
||||
.start-btn {
|
||||
padding: 18px 45px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.progress-container {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 10px;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.progress-bar::after {
|
||||
content: "";
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: var(--width, 0%);
|
||||
background: linear-gradient(to right, #4a00e0, #8e2de2);
|
||||
transition: width 0.5s ease;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
text-align: right;
|
||||
font-size: 1rem;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.question-container {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.question-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 20px;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.question-header h2 {
|
||||
color: #333;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.5;
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.selection-info {
|
||||
background-color: #f0f4ff;
|
||||
padding: 10px 20px;
|
||||
border-radius: 25px;
|
||||
font-size: 1rem;
|
||||
color: #4a00e0;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
border: 2px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.selection-info i {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
/* Блок обратной связи */
|
||||
.feedback-container {
|
||||
margin-bottom: 20px;
|
||||
animation: fadeIn 0.5s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.feedback {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 15px;
|
||||
font-size: 1.1rem;
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
border-left: 5px solid;
|
||||
}
|
||||
|
||||
.feedback i {
|
||||
font-size: 1.8rem;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.feedback-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.feedback-title {
|
||||
font-weight: 700;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.feedback-detail {
|
||||
opacity: 0.9;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.correct-feedback {
|
||||
background-color: #e7f7ef;
|
||||
color: #2e7d32;
|
||||
border-left-color: #2e7d32;
|
||||
}
|
||||
|
||||
.partially-feedback {
|
||||
background-color: #fff8e1;
|
||||
color: #f57c00;
|
||||
border-left-color: #ff9800;
|
||||
}
|
||||
|
||||
.incorrect-feedback {
|
||||
background-color: #fdeaea;
|
||||
color: #c62828;
|
||||
border-left-color: #c62828;
|
||||
}
|
||||
|
||||
.options-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.option {
|
||||
background-color: #f8f9fa;
|
||||
border: 2px solid #e0e0e0;
|
||||
border-radius: 12px;
|
||||
padding: 18px 20px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.option:hover {
|
||||
background-color: #eef2ff;
|
||||
border-color: #8e2de2;
|
||||
}
|
||||
|
||||
.option.selected {
|
||||
background-color: #e6f7ff;
|
||||
border-color: #4a00e0;
|
||||
box-shadow: 0 3px 8px rgba(74, 0, 224, 0.1);
|
||||
}
|
||||
|
||||
.option.correct {
|
||||
background-color: #e7f7ef;
|
||||
border-color: #2e7d32;
|
||||
color: #2e7d32;
|
||||
}
|
||||
|
||||
.option.partial {
|
||||
background-color: #fff8e1;
|
||||
border-color: #ff9800;
|
||||
color: #f57c00;
|
||||
}
|
||||
|
||||
.option.incorrect {
|
||||
background-color: #fdeaea;
|
||||
border-color: #c62828;
|
||||
color: #c62828;
|
||||
}
|
||||
|
||||
.option.checked {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.option.checked:hover {
|
||||
background-color: inherit;
|
||||
border-color: inherit;
|
||||
}
|
||||
|
||||
.option-checkbox {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 2px solid #4a00e0;
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.option.selected .option-checkbox {
|
||||
background-color: #4a00e0;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.option.selected .option-checkbox::after {
|
||||
content: "✓";
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.option.correct .option-checkbox {
|
||||
background-color: #2e7d32;
|
||||
border-color: #2e7d32;
|
||||
}
|
||||
|
||||
.option.partial .option-checkbox {
|
||||
background-color: #ff9800;
|
||||
border-color: #ff9800;
|
||||
}
|
||||
|
||||
.option.incorrect .option-checkbox {
|
||||
background-color: #c62828;
|
||||
border-color: #c62828;
|
||||
}
|
||||
|
||||
.option-text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.question-hint {
|
||||
background-color: #f0f4ff;
|
||||
padding: 12px 20px;
|
||||
border-radius: 10px;
|
||||
color: #4a00e0;
|
||||
font-size: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
border-left: 4px solid #4a00e0;
|
||||
}
|
||||
|
||||
.navigation {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 30px;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.prev-btn,
|
||||
.check-btn,
|
||||
.next-btn,
|
||||
.submit-btn {
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
.result-content {
|
||||
text-align: center;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.result-content h2 {
|
||||
color: #333;
|
||||
margin-bottom: 25px;
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.score-circle {
|
||||
margin: 30px auto;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(#4a00e0 0%, #e0e0e0 0%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.circle::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 170px;
|
||||
height: 170px;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.circle span {
|
||||
font-size: 3.5rem;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.score-label {
|
||||
font-size: 1rem;
|
||||
color: #666;
|
||||
z-index: 1;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.percentage {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
color: #4a00e0;
|
||||
}
|
||||
|
||||
.result-details {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.result-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 15px 25px;
|
||||
border-radius: 12px;
|
||||
font-size: 1.2rem;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.result-item i {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.correct {
|
||||
background-color: #e7f7ef;
|
||||
color: #2e7d32;
|
||||
}
|
||||
|
||||
.partially {
|
||||
background-color: #fff8e1;
|
||||
color: #f57c00;
|
||||
}
|
||||
|
||||
.incorrect {
|
||||
background-color: #fdeaea;
|
||||
color: #c62828;
|
||||
}
|
||||
|
||||
.result-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.restart-btn,
|
||||
.review-btn {
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
.review-header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.review-header h2 {
|
||||
color: #333;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.review-header p {
|
||||
color: #666;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.correct-badge,
|
||||
.partial-badge,
|
||||
.incorrect-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 5px 12px;
|
||||
border-radius: 15px;
|
||||
font-size: 0.9rem;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.correct-badge {
|
||||
background-color: #e7f7ef;
|
||||
color: #2e7d32;
|
||||
}
|
||||
|
||||
.partial-badge {
|
||||
background-color: #fff8e1;
|
||||
color: #f57c00;
|
||||
}
|
||||
|
||||
.incorrect-badge {
|
||||
background-color: #fdeaea;
|
||||
color: #c62828;
|
||||
}
|
||||
|
||||
.review-item {
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 15px;
|
||||
padding: 25px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.review-question {
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 20px;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.question-status {
|
||||
font-size: 1rem;
|
||||
padding: 5px 15px;
|
||||
border-radius: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.status-correct {
|
||||
background-color: #e7f7ef;
|
||||
color: #2e7d32;
|
||||
}
|
||||
|
||||
.status-partial {
|
||||
background-color: #fff8e1;
|
||||
color: #f57c00;
|
||||
}
|
||||
|
||||
.status-incorrect {
|
||||
background-color: #fdeaea;
|
||||
color: #c62828;
|
||||
}
|
||||
|
||||
.review-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.review-option {
|
||||
padding: 12px 15px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
border-left: 4px solid transparent;
|
||||
}
|
||||
|
||||
.correct-answer {
|
||||
background-color: #e7f7ef;
|
||||
border-left-color: #2e7d32;
|
||||
}
|
||||
|
||||
.user-correct {
|
||||
background-color: #e7f7ef;
|
||||
border-left-color: #2e7d32;
|
||||
}
|
||||
|
||||
.user-partial {
|
||||
background-color: #fff8e1;
|
||||
border-left-color: #ff9800;
|
||||
}
|
||||
|
||||
.user-incorrect {
|
||||
background-color: #fdeaea;
|
||||
border-left-color: #c62828;
|
||||
}
|
||||
|
||||
.review-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: #f8f9fa;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-size: 0.9rem;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.container {
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.quiz-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.question-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.question-header h2 {
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
.navigation {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.prev-btn,
|
||||
.check-btn,
|
||||
.next-btn,
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
.result-details {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.result-item {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
.result-actions {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.restart-btn,
|
||||
.review-btn {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
min-width: auto;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user