Гобелен - кликните для возврата на главную
Не прошло и месяца а Фурмановская ЦРБ в очередной раз попала в историю. На этот раз сотрудница клеветала на пациентов, а именно огласку получил случай когда сотрудница назвала пациента алкашём.
Так почему бы не начать использовать обход блокировки YouTube при том что техническая возможность используя расширение nikolaevevge для браузера Mozilla Firefox уже появилась, а объем полезной(и не очень) информации на видеохостинге YouTube, по мнению некоторых диванных экспертов, меньше не стал.
Ровно 3 года назад произошло событие, которое подарило жителям планеты Змеля новый чистый праздник 6 апреля - в этот замечательный день земля забрала гнить негодяя и СПАМера Владимира Вольфовича Жириновского.
Как бы не обстояли дела в области культуры и IT-технологий, Самосвал писал статьи на связанные темы и планирует ещё написать.
На очередном конкурсе танцев, школьница отлично выступила.
Вот та самая информация: программа для продвижения канала YouTube, эта информация выложена уже несколько лет, при этом просмотров не много, а метод который описан в данном видео действительно помогает продвигать видео в YouTube.
Начал разбираться с информацией которая находится в HTTPS клиентском запросе рукопожатия.
Обратите внимание! Объект изображённый на гобилене может отличаться от общепринятого вида описанного объекта. Тут дело в том что художник видит именно так!
Попробуйте написать на PHP страницу тестирования. То есть загружается вопрос и варианты ответов. Ответ может быть единственным верным или могут быть несколько(checkbox). База данных для хранения MySQL. За запросов используйте PDO. Сейчас требуется написать не всю систему а PHP скрипт который обрабатывает вывод одного конкретного вопроса и обрабатывает ответ на него.
Для создания PHP-скрипта, который выводит вопрос с вариантами ответов и обрабатывает ответ на него, можно использовать следующий подход. Предположим, что у вас есть база данных MySQL с таблицей questions, которая содержит вопросы, и таблицей answers, которая содержит варианты ответов для каждого вопроса.
Таблица questions:
Таблица answers:
PHP-скрипт
<?php
// Настройки подключения к базе данных
$host = 'localhost';
$db = 'test_db';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
// Получаем ID вопроса из GET-запроса
$question_id = $_GET['question_id'] ?? 1; // По умолчанию берем вопрос с ID 1
// Запрос на получение вопроса
$stmt = $pdo->prepare("SELECT * FROM questions WHERE id = ?");
$stmt->execute([$question_id]);
$question = $stmt->fetch();
if (!$question) {
die("Вопрос не найден");
}
// Запрос на получение ответов для вопроса
$stmt = $pdo->prepare("SELECT * FROM answers WHERE question_id = ?");
$stmt->execute([$question_id]);
$answers = $stmt->fetchAll();
// Обработка ответа пользователя
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$user_answers = $_POST['answers'] ?? [];
// Проверка ответов
$correct_answers = array_filter($answers, function($answer) {
return $answer['is_correct'];
});
$correct_answer_ids = array_column($correct_answers, 'id');
if ($question['is_multiple_choice']) {
// Для вопросов с несколькими правильными ответами
$is_correct = empty(array_diff($correct_answer_ids, $user_answers)) && empty(array_diff($user_answers, $correct_answer_ids));
} else {
// Для вопросов с одним правильным ответом
$is_correct = count($user_answers) === 1 && in_array($user_answers[0], $correct_answer_ids);
}
if ($is_correct) {
echo "Правильно!";
} else {
echo "Неправильно!";
}
}
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Тестирование</title>
</head>
<body>
<h1><?= htmlspecialchars($question['question_text']) ?></h1>
<form method="post">
<?php foreach ($answers as $answer): ?>
<label>
<?php if ($question['is_multiple_choice']): ?>
<input type="checkbox" name="answers[]" value="<?= $answer['id'] ?>">
<?php else: ?>
<input type="radio" name="answers[]" value="<?= $answer['id'] ?>">
<?php endif; ?>
<?= htmlspecialchars($answer['answer_text']) ?>
</label><br>
<?php endforeach; ?>
<button type="submit">Ответить</button>
</form>
</body>
</html>
Описание скрипта:
Вывод формы: Форма с вопросом и вариантами ответов выводится на странице. В зависимости от типа вопроса (один или несколько правильных ответов) используются либо радиокнопки, либо чекбоксы.
Этот скрипт можно расширять и дорабатывать в зависимости от требований вашей системы тестирования.
А как бы Вы доработали если суммарно на тест отводится определённое место? Я понимаю что такой параметр предполагается хранить в таблице базы данных с информацией о тесте(которая включает в себя в свою очередь связь с таблицей вопросов), так вот предлагаю такую таблицу пока не делать, я просто объявить в переменной значение оставшегося времени, например в секундах. То-есть реализация этого дополнения может ограничиваться указанной выше переменной, JavaScript-сценарием(который контролирует время при выполнении теста и показывает сколько времени осталось), а так же PHP обработчиком ситуации завершения теста(тут есть разные варианты: сработает ли стандартное завершение теста как при получении всех ответов или ситуация с истечением времени будет обрабатываться как то иначе).
Для реализации ограничения по времени на выполнение теста можно использовать комбинацию JavaScript для отслеживания времени на стороне клиента и PHP для обработки завершения теста на стороне сервера. Вот как можно доработать ваш скрипт:
1. Добавление переменной с оставшимся временем
В PHP-скрипте объявим переменную, которая будет хранить оставшееся время в секундах:
$remaining_time = 600; // 10 минут в секундах
2. JavaScript для отслеживания времени
Добавим JavaScript-код, который будет отслеживать оставшееся время и автоматически завершать тест, когда время истечет:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Тестирование</title>
<script>
let remainingTime = <?= $remaining_time ?>; // Оставшееся время в секундах
function updateTimer() {
const minutes = Math.floor(remainingTime / 60);
const seconds = remainingTime % 60;
document.getElementById('timer').innerText = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
if (remainingTime <= 0) {
clearInterval(timerInterval);
alert("Время вышло!");
document.getElementById('testForm').submit();
} else {
remainingTime--;
}
}
const timerInterval = setInterval(updateTimer, 1000);
</script>
</head>
<body>
<h1><?= htmlspecialchars($question['question_text']) ?></h1>
<div>Оставшееся время: <span id="timer"></span></div>
<form id="testForm" method="post">
<?php foreach ($answers as $answer): ?>
<label>
<?php if ($question['is_multiple_choice']): ?>
<input type="checkbox" name="answers[]" value="<?= $answer['id'] ?>">
<?php else: ?>
<input type="radio" name="answers[]" value="<?= $answer['id'] ?>">
<?php endif; ?>
<?= htmlspecialchars($answer['answer_text']) ?>
</label><br>
<?php endforeach; ?>
<button type="submit">Ответить</button>
</form>
</body>
</html>
В PHP-скрипте добавим проверку на истечение времени. Если время истекло, завершаем тест и выводим сообщение:
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$user_answers = $_POST['answers'] ?? [];
// Проверка, истекло ли время
if ($remaining_time <= 0) {
echo "Время вышло! Тест завершен.";
// Здесь можно добавить логику для завершения теста, например, сохранение результатов
exit;
}
// Проверка ответов
$correct_answers = array_filter($answers, function($answer) {
return $answer['is_correct'];
});
$correct_answer_ids = array_column($correct_answers, 'id');
if ($question['is_multiple_choice']) {
// Для вопросов с несколькими правильными ответами
$is_correct = empty(array_diff($correct_answer_ids, $user_answers)) && empty(array_diff($user_answers, $correct_answer_ids));
} else {
// Для вопросов с одним правильным ответом
$is_correct = count($user_answers) === 1 && in_array($user_answers[0], $correct_answer_ids);
}
if ($is_correct) {
echo "Правильно!";
} else {
echo "Неправильно!";
}
}
4. Дополнительные улучшения
Сохранение результатов теста: Можно добавить логику для сохранения результатов теста в базу данных, включая информацию о том, был ли тест завершен по истечении времени.
Рефакторинг кода: Для улучшения читаемости и поддерживаемости кода можно вынести логику работы с базой данных и обработки ответов в отдельные функции или классы.
Уведомления пользователя: Можно добавить более сложные уведомления пользователю о том, что время истекает, например, показывать предупреждение за 1 минуту до окончания времени.
Таким образом, вы сможете реализовать ограничение по времени на выполнение теста с использованием JavaScript для отслеживания времени на стороне клиента и PHP для обработки завершения теста на стороне сервера.
Можете предложить вариант административной части системы? Рассматривается только страница редактирования конкретного вопроса теста и ответов к нему. Важным моментом является возможность визуального редактирования как вопросов так и ответов к нему, а так же возможность включать не ограниченное количество изображений и видеозаписей как к ответу так и к вопросу. Соответственно требуется так же PHP скрипт который корректно будет сохранять информацию о ответах и вопросах на сервере, включая медиа информацию.
Для реализации административной части системы, включая страницу редактирования вопроса и ответов с поддержкой медиафайлов (изображений и видео), можно использовать следующий подход. Мы создадим PHP-скрипт, который позволит администратору редактировать вопрос, добавлять/удалять ответы, а также загружать медиафайлы.
Структура базы данных
Таблица questions:
Таблица answers:
Таблица media:
PHP-скрипт для редактирования вопроса
<?php
// Настройки подключения к базе данных
$host = 'localhost';
$db = 'test_db';
$user = 'root';
$pass = '';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
// Получаем ID вопроса из GET-запроса
$question_id = $_GET['question_id'] ?? null;
if ($question_id) {
// Запрос на получение вопроса
$stmt = $pdo->prepare("SELECT * FROM questions WHERE id = ?");
$stmt->execute([$question_id]);
$question = $stmt->fetch();
// Запрос на получение ответов для вопроса
$stmt = $pdo->prepare("SELECT * FROM answers WHERE question_id = ?");
$stmt->execute([$question_id]);
$answers = $stmt->fetchAll();
// Запрос на получение медиафайлов для вопроса и ответов
$stmt = $pdo->prepare("SELECT * FROM media WHERE question_id = ? OR answer_id IN (SELECT id FROM answers WHERE question_id = ?)");
$stmt->execute([$question_id, $question_id]);
$media = $stmt->fetchAll();
}
// Обработка формы
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$question_text = $_POST['question_text'];
$is_multiple_choice = $_POST['is_multiple_choice'] ?? 0;
// Обновляем вопрос
$stmt = $pdo->prepare("UPDATE questions SET question_text = ?, is_multiple_choice = ? WHERE id = ?");
$stmt->execute([$question_text, $is_multiple_choice, $question_id]);
// Обработка ответов
foreach ($_POST['answers'] as $answer_id => $answer_data) {
$answer_text = $answer_data['text'];
$is_correct = $answer_data['is_correct'] ?? 0;
$stmt = $pdo->prepare("UPDATE answers SET answer_text = ?, is_correct = ? WHERE id = ?");
$stmt->execute([$answer_text, $is_correct, $answer_id]);
}
// Обработка медиафайлов
foreach ($_FILES['media'] as $media_data) {
if ($media_data['error'] === UPLOAD_ERR_OK) {
$file_path = 'uploads/' . basename($media_data['name']);
move_uploaded_file($media_data['tmp_name'], $file_path);
$file_type = strpos($media_data['type'], 'image') !== false ? 'image' : 'video';
$stmt = $pdo->prepare("INSERT INTO media (question_id, answer_id, file_path, file_type) VALUES (?, ?, ?, ?)");
$stmt->execute([$question_id, null, $file_path, $file_type]);
}
}
// Редирект на страницу редактирования
header("Location: edit_question.php?question_id=$question_id");
exit;
}
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Редактирование вопроса</title>
</head>
<body>
<h1>Редактирование вопроса</h1>
<form method="post" enctype="multipart/form-data">
<div>
<label>Текст вопроса:</label>
<textarea name="question_text"><?= htmlspecialchars($question['question_text']) ?></textarea>
</div>
<div>
<label>
<input type="checkbox" name="is_multiple_choice" value="1" <?= $question['is_multiple_choice'] ? 'checked' : '' ?>>
Несколько правильных ответов
</label>
</div>
<div>
<h2>Ответы:</h2>
<?php foreach ($answers as $answer): ?>
<div>
<label>Текст ответа:</label>
<textarea name="answers[<?= $answer['id'] ?>][text]"><?= htmlspecialchars($answer['answer_text']) ?></textarea>
<label>
<input type="checkbox" name="answers[<?= $answer['id'] ?>][is_correct]" value="1" <?= $answer['is_correct'] ? 'checked' : '' ?>>
Правильный ответ
</label>
</div>
<?php endforeach; ?>
</div>
<div>
<h2>Медиафайлы:</h2>
<input type="file" name="media[]" multiple>
</div>
<button type="submit">Сохранить</button>
</form>
</body>
</html>
Описание скрипта:
Дополнительные улучшения:
Этот скрипт предоставляет базовую функциональность для редактирования вопросов и ответов с поддержкой медиафайлов. Вы можете расширять и дорабатывать его в зависимости от ваших требований.
С учётом того что планировалось систему использовать совместно с CRM Битрикс24, приведу пример экспорта таблицы базы данных(была выбрана таблица b_abtest) для того чтобы при создании таблицы было видно какие кодировки для каких ячеек использовать(по факту выбрал одну из первых попавшихся таблиц, можно было выбрать и какую ниубдь другую).
CREATE TABLE `b_abtest` (
`ID` int(11) NOT NULL,
`SITE_ID` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`ACTIVE` char(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'N',
`ENABLED` char(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'N',
`NAME` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`DESCR` text COLLATE utf8_unicode_ci,
`TEST_DATA` text COLLATE utf8_unicode_ci NOT NULL,
`START_DATE` datetime DEFAULT NULL,
`STOP_DATE` datetime DEFAULT NULL,
`DURATION` int(11) NOT NULL DEFAULT '0',
`PORTION` int(11) NOT NULL DEFAULT '0',
`MIN_AMOUNT` int(11) DEFAULT NULL,
`USER_ID` int(11) DEFAULT NULL,
`SORT` int(11) NOT NULL DEFAULT '100'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `b_abtest`
ADD PRIMARY KEY (`ID`);
ALTER TABLE `b_abtest`
MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;
CREATE TABLE `nikevknowledge_question` (
`id` int(11) NOT NULL,
`test_id` int(11) NOT NULL DEFAULT '0',
`multiple_choice_flag` int(11) NOT NULL DEFAULT '0',
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`text` text COLLATE utf8_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `nikevknowledge_question`
ADD PRIMARY KEY (`id`);
ALTER TABLE `nikevknowledge_question`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;
CREATE TABLE `nikevknowledge_answer` (
`id` int(11) NOT NULL,
`question_id` int(11) NOT NULL DEFAULT '0',
`correct_flag` int(11) NOT NULL DEFAULT '0',
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`text` text COLLATE utf8_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `nikevknowledge_answer`
ADD PRIMARY KEY (`id`);
ALTER TABLE `nikevknowledge_answer`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;
CREATE TABLE `nikevknowledge_test` (
`id` int(11) NOT NULL,
`timelimit` int(11) NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`text` text COLLATE utf8_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `nikevknowledge_test`
ADD PRIMARY KEY (`id`);
ALTER TABLE `nikevknowledge_test`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
COMMIT;
Вы так же можете прочитать следующие статьи: