Przeglądaj źródła

Загрузить файлы 'Лекции/П2.5.500_Использование_принтеров_для_печати_конфиденциальных_документов'

u23-27burdyko 5 dni temu
rodzic
commit
1a8ae2f049

+ 527 - 0
Лекции/П2.5.500_Использование_принтеров_для_печати_конфиденциальных_документов/burdyko.html.html

@@ -0,0 +1,527 @@
+<!DOCTYPE html>
+<html lang="ru">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Агент Secure Print — игра по безопасности печати</title>
+    <style>
+        * {
+            box-sizing: border-box;
+            user-select: none;
+        }
+        body {
+            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+            background: linear-gradient(135deg, #1a2a3a, #0d1c2a);
+            min-height: 100vh;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            margin: 0;
+            padding: 20px;
+        }
+        .game-container {
+            max-width: 800px;
+            width: 100%;
+            background: #f5f3ef;
+            border-radius: 32px;
+            box-shadow: 0 20px 40px rgba(0,0,0,0.4);
+            overflow: hidden;
+        }
+        .scene {
+            padding: 30px 25px;
+        }
+        .scene-header {
+            display: flex;
+            justify-content: space-between;
+            align-items: baseline;
+            border-bottom: 2px solid #d0b87a;
+            margin-bottom: 25px;
+            flex-wrap: wrap;
+        }
+        .scene-title {
+            font-size: 1.8rem;
+            font-weight: bold;
+            color: #2c3e2f;
+        }
+        .score {
+            background: #2c3e2f;
+            color: #f9e0a8;
+            padding: 6px 14px;
+            border-radius: 40px;
+            font-weight: bold;
+        }
+        .scene-content {
+            min-height: 380px;
+        }
+        .question-block {
+            background: white;
+            border-radius: 24px;
+            padding: 20px;
+            margin-bottom: 20px;
+            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
+            border: 1px solid #e0cfb0;
+        }
+        .question-text {
+            font-weight: bold;
+            font-size: 1.2rem;
+            margin-bottom: 20px;
+            color: #2c3e2f;
+            background: #f0eadb;
+            padding: 15px;
+            border-radius: 16px;
+        }
+        .answers {
+            display: flex;
+            flex-direction: column;
+            gap: 12px;
+        }
+        .answer-option {
+            background: #f9f7f2;
+            padding: 14px 18px;
+            border-radius: 16px;
+            cursor: pointer;
+            border: 2px solid #e0cfb0;
+            transition: all 0.1s;
+            font-size: 1rem;
+        }
+        .answer-option:hover {
+            background: #e8dfcc;
+            border-color: #b98f4a;
+            transform: scale(1.01);
+        }
+        .element {
+            background: white;
+            border-radius: 24px;
+            padding: 20px;
+            margin-bottom: 20px;
+            box-shadow: 0 4px 12px rgba(0,0,0,0.1);
+            cursor: pointer;
+            border: 1px solid #e0cfb0;
+        }
+        .element:hover {
+            background: #fffaf2;
+            border-color: #b98f4a;
+        }
+        .element-title {
+            font-weight: bold;
+            font-size: 1.3rem;
+            margin-bottom: 12px;
+            color: #a45d2e;
+            display: flex;
+            align-items: center;
+            gap: 12px;
+        }
+        .actions {
+            margin-top: 20px;
+            display: flex;
+            flex-wrap: wrap;
+            gap: 15px;
+        }
+        button {
+            background: #2c5f2d;
+            border: none;
+            color: white;
+            font-weight: bold;
+            padding: 12px 24px;
+            border-radius: 40px;
+            font-size: 1rem;
+            cursor: pointer;
+            transition: 0.1s;
+        }
+        button:hover {
+            background: #1f4520;
+            transform: scale(0.97);
+        }
+        .message {
+            background: #e9e3d5;
+            border-left: 6px solid #b98f4a;
+            padding: 12px;
+            margin-top: 20px;
+            border-radius: 16px;
+            font-style: italic;
+        }
+        .game-over {
+            background: #8b3c2c;
+            color: white;
+            text-align: center;
+            padding: 30px;
+            border-radius: 20px;
+        }
+        .win {
+            background: #2c5f2d;
+        }
+        footer {
+            background: #e0cfb0;
+            padding: 12px;
+            text-align: center;
+            font-size: 0.8rem;
+            color: #2c3e2f;
+        }
+        .feedback {
+            margin-top: 15px;
+            padding: 10px;
+            border-radius: 12px;
+            font-weight: bold;
+        }
+        .feedback-correct {
+            background: #c8e6c9;
+            color: #1b5e20;
+            border-left: 4px solid #2e7d32;
+        }
+        .feedback-wrong {
+            background: #ffcdd2;
+            color: #c62828;
+            border-left: 4px solid #d32f2f;
+        }
+        hr {
+            margin: 15px 0;
+        }
+    </style>
+</head>
+<body>
+<div class="game-container" id="gameRoot"></div>
+
+<script>
+    // СОСТОЯНИЕ ИГРЫ
+    let currentScene = 1;
+    let score = 0;
+    let gameActive = true;
+    let finalMessage = "";
+    let waitingForNext = false;
+
+    function render() {
+        if (!gameActive) {
+            const root = document.getElementById('gameRoot');
+            root.innerHTML = `
+                <div class="scene">
+                    <div class="game-over ${finalMessage.includes('ПОБЕДА') ? 'win' : ''}">
+                        <h2>🔐 ${finalMessage.includes('ПОБЕДА') ? 'ПОБЕДА!' : 'ИГРА ОКОНЧЕНА'}</h2>
+                        <p>${finalMessage}</p>
+                        <p><strong>Итоговый счёт безопасности: ${score}</strong></p>
+                        <button onclick="resetGame()">🔄 Начать заново</button>
+                    </div>
+                </div>
+            `;
+            return;
+        }
+
+        const sceneData = getSceneData(currentScene);
+        if (!sceneData) return;
+
+        const root = document.getElementById('gameRoot');
+        
+        let contentHtml = '';
+        
+        if (sceneData.type === 'quiz') {
+            // Формат с вариантами ответов (как в требовании вариант №1)
+            contentHtml = `
+                <div class="question-block">
+                    <div class="question-text">❓ ${sceneData.question}</div>
+                    <div class="answers" id="answersContainer">
+                        ${sceneData.answers.map((ans, idx) => `
+                            <div class="answer-option" data-answer-index="${idx}">
+                                ${ans.text}
+                            </div>
+                        `).join('')}
+                    </div>
+                    <div id="quizFeedback" class="feedback" style="display:none;"></div>
+                </div>
+            `;
+        } else {
+            // Обычная сцена с элементами
+            let elementsHtml = '';
+            for (let el of sceneData.elements || []) {
+                elementsHtml += `
+                    <div class="element" data-element-id="${el.id}">
+                        <div class="element-title">
+                            <span>📄 ${el.title}</span>
+                        </div>
+                        <div class="element-desc">${el.desc}</div>
+                    </div>
+                `;
+            }
+            contentHtml = elementsHtml;
+        }
+
+        let actionsHtml = '';
+        for (let act of sceneData.actions || []) {
+            actionsHtml += `<button data-action-id="${act.id}">${act.label}</button>`;
+        }
+
+        const html = `
+            <div class="scene">
+                <div class="scene-header">
+                    <div class="scene-title">${sceneData.title}</div>
+                    <div class="score">🔒 Безопасность: ${score}</div>
+                </div>
+                <div class="scene-content">
+                    ${contentHtml}
+                    ${actionsHtml ? `<div class="actions">${actionsHtml}</div>` : ''}
+                    <div class="message" id="sceneMessage">${sceneData.defaultMessage || 'Выберите действие...'}</div>
+                </div>
+            </div>
+            <footer>🖨️ Агент Secure Print — защита конфиденциальной печати</footer>
+        `;
+        root.innerHTML = html;
+
+        // Обработчики для элементов
+        for (let el of sceneData.elements || []) {
+            const domEl = document.querySelector(`.element[data-element-id="${el.id}"]`);
+            if (domEl && el.onClick) {
+                domEl.addEventListener('click', () => {
+                    if (gameActive && !waitingForNext) handleActionResult(el.onClick());
+                });
+            }
+        }
+
+        // Обработчики для кнопок
+        for (let act of sceneData.actions || []) {
+            const btn = document.querySelector(`button[data-action-id="${act.id}"]`);
+            if (btn) {
+                btn.addEventListener('click', () => {
+                    if (gameActive && !waitingForNext) handleActionResult(act.onClick());
+                });
+            }
+        }
+
+        // Обработчики для викторины (варианты ответов)
+        if (sceneData.type === 'quiz') {
+            const answersDivs = document.querySelectorAll('.answer-option');
+            answersDivs.forEach((div, idx) => {
+                div.addEventListener('click', () => {
+                    if (gameActive && !waitingForNext) {
+                        const answer = sceneData.answers[idx];
+                        const feedbackDiv = document.getElementById('quizFeedback');
+                        feedbackDiv.style.display = 'block';
+                        
+                        if (answer.correct) {
+                            feedbackDiv.innerHTML = `✅ Правильно! ${answer.feedback || ''}`;
+                            feedbackDiv.className = 'feedback feedback-correct';
+                            score += sceneData.pointsForCorrect || 25;
+                            document.querySelector('.score').innerHTML = `🔒 Безопасность: ${score}`;
+                            
+                            // Автоматический переход после правильного ответа
+                            waitingForNext = true;
+                            setTimeout(() => {
+                                if (sceneData.nextSceneOnCorrect) {
+                                    currentScene = sceneData.nextSceneOnCorrect;
+                                    waitingForNext = false;
+                                    render();
+                                } else if (sceneData.nextScene) {
+                                    currentScene = sceneData.nextScene;
+                                    waitingForNext = false;
+                                    render();
+                                }
+                            }, 1500);
+                        } else {
+                            feedbackDiv.innerHTML = `❌ Неправильно. ${answer.feedback || 'Попробуйте ещё раз!'}`;
+                            feedbackDiv.className = 'feedback feedback-wrong';
+                            if (sceneData.penaltyOnWrong) {
+                                score += sceneData.penaltyOnWrong;
+                                document.querySelector('.score').innerHTML = `🔒 Безопасность: ${score}`;
+                            }
+                            // Блокируем ответы на 1 секунду, но не переходим
+                            waitingForNext = true;
+                            setTimeout(() => {
+                                waitingForNext = false;
+                                feedbackDiv.style.display = 'none';
+                            }, 1200);
+                        }
+                    }
+                });
+            });
+        }
+    }
+
+    function handleActionResult(result) {
+        if (!result) return;
+        
+        if (result.message) {
+            document.getElementById('sceneMessage').innerText = result.message;
+        }
+        if (result.scoreChange) {
+            score += result.scoreChange;
+        }
+        if (result.nextScene) {
+            currentScene = result.nextScene;
+            render();
+        }
+        if (result.gameOver) {
+            gameActive = false;
+            finalMessage = result.gameOver;
+            render();
+        }
+        if (!result.nextScene && !result.gameOver && result.scoreChange !== undefined) {
+            // Обновляем только счёт без перехода
+            render();
+        }
+    }
+
+    function getSceneData(sceneId) {
+        // СЦЕНА 1
+        if (sceneId === 1) {
+            return {
+                title: '📥 Сцена 1: Приёмное отделение',
+                type: 'default',
+                elements: [
+                    {
+                        id: 'convent',
+                        title: '📨 Жёлтый конверт с грифом "Срочно"',
+                        desc: 'Сотрудник Иванов отправил на печать 200 страниц плана “Метеор”. Безопасно ли это?',
+                    }
+                ],
+                actions: [
+                    {
+                        id: 'allow',
+                        label: '✅ Разрешить печать',
+                        onClick: () => ({ gameOver: '❌ УТЕЧКА! Документы остались в памяти принтера. Вы проиграли.', scoreChange: -100 })
+                    },
+                    {
+                        id: 'check',
+                        label: '🔍 Запросить уточнение и проверить настройки',
+                        onClick: () => ({ message: 'Правильно! Нужно проверить безопасность.', nextScene: 2, scoreChange: 20 })
+                    }
+                ],
+                defaultMessage: 'Выберите действие: разрешить печать или запросить уточнение.'
+            };
+        }
+
+        // СЦЕНА 2 - ПЕРЕДЕЛАНА В ВИКТОРИНУ С ВАРИАНТАМИ ОТВЕТОВ
+        if (sceneId === 2) {
+            return {
+                title: '⚙️ Сцена 2: Настройка безопасной печати',
+                type: 'quiz',
+                question: 'Какое действие НЕОБХОДИМО выполнить перед печатью конфиденциального документа на сетевом принтере?',
+                answers: [
+                    { 
+                        text: '🔐 Включить функцию Secure Print (печать по PIN-коду)', 
+                        correct: true,
+                        feedback: 'Верно! Secure Print требует ввода PIN-кода на самом принтере, документ не печатается, пока вы не подойдёте к устройству.'
+                    },
+                    { 
+                        text: '📤 Отправить документ на печать и забрать через час', 
+                        correct: false,
+                        feedback: 'Ошибка! Документ может быть перехвачен или прочитан посторонними. Забирать распечатку нужно сразу.'
+                    },
+                    { 
+                        text: '💾 Сохранить документ в памяти принтера навсегда', 
+                        correct: false,
+                        feedback: 'Неверно! Хранение конфиденциальных данных в памяти принтера — это прямой риск утечки.'
+                    },
+                    { 
+                        text: '📧 Отправить документ на печать по электронной почте без шифрования', 
+                        correct: false,
+                        feedback: 'Опасно! Отправка заданий печати по незащищённым каналам может привести к перехвату данных.'
+                    }
+                ],
+                pointsForCorrect: 30,
+                penaltyOnWrong: -10,
+                nextSceneOnCorrect: 3,
+                defaultMessage: 'Выберите правильный вариант ответа.'
+            };
+        }
+
+        // СЦЕНА 3: Конфликт в офисе
+        if (sceneId === 3) {
+            return {
+                title: '🏢 Сцена 3: Конфликт в офисе',
+                type: 'default',
+                elements: [
+                    {
+                        id: 'colleague',
+                        title: '🧑‍💼 Взволнованный сотрудник с папкой "Секретно"',
+                        desc: '"Мне срочно нужно 5 копий, сисадмин занят! Можно напечатать на соседнем обычном принтере?"',
+                    }
+                ],
+                actions: [
+                    {
+                        id: 'bad',
+                        label: '⚠️ Печатать на незащищённом принтере',
+                        onClick: () => ({ gameOver: '📡 Перехват данных! Незащищённый принтер скомпрометирован. Игра окончена.', scoreChange: -999 })
+                    },
+                    {
+                        id: 'good',
+                        label: '⏳ Подождать и использовать безопасный принтер с Secure Print',
+                        onClick: () => ({ nextScene: 4, message: 'Правильный выбор! Конфиденциальность сохранена.', scoreChange: 50 })
+                    }
+                ],
+                defaultMessage: 'Выберите, как поступить в стрессовой ситуации.'
+            };
+        }
+
+        // СЦЕНА 4: Списание старого МФУ
+        if (sceneId === 4) {
+            return {
+                title: '🗑️ Сцена 4: Списание старого МФУ',
+                type: 'default',
+                elements: [
+                    {
+                        id: 'oldprinter',
+                        title: '🖨️ Старый принтер с табличкой "К списанию"',
+                        desc: 'Внутри жёсткий диск с остатками конфиденциальных документов.',
+                    }
+                ],
+                actions: [
+                    {
+                        id: 'destroySW',
+                        label: '💾 Запустить сертифицированную программу "Уничтожитель данных"',
+                        onClick: () => ({ nextScene: 5, message: 'Диск надёжно стёрт. Молодец!', scoreChange: 40 })
+                    },
+                    {
+                        id: 'destroyPhys',
+                        label: '🔨 Физически разбить диск и составить акт',
+                        onClick: () => ({ nextScene: 5, message: 'Физическое уничтожение зафиксировано. Безопасно.', scoreChange: 40 })
+                    },
+                    {
+                        id: 'throw',
+                        label: '🗑️ Просто выбросить принтер с диском',
+                        onClick: () => ({ gameOver: '💀 Утечка! Злоумышленник извлёк диск из мусора.', scoreChange: -100 })
+                    }
+                ],
+                defaultMessage: 'Выберите корректный способ уничтожения данных.'
+            };
+        }
+
+        // СЦЕНА 5: Финальный аудит
+        if (sceneId === 5) {
+            return {
+                title: '📋 Сцена 5: Финальный аудит',
+                type: 'default',
+                elements: [
+                    {
+                        id: 'logbook',
+                        title: '📜 Журнал печати за месяц',
+                        desc: 'Обнаружены 3 ночные печати по 500 страниц с компьютера Петрова.',
+                    }
+                ],
+                actions: [
+                    {
+                        id: 'warn',
+                        label: '📢 Выговор и обязательное обучение',
+                        onClick: () => ({ gameOver: '🏆 ПОБЕДА! Политика безопасности усилена. Игра пройдена!', scoreChange: 100 })
+                    },
+                    {
+                        id: 'fire',
+                        label: '⚡ Немедленное увольнение без разбора',
+                        onClick: () => ({ gameOver: '😐 Нейтральный финал: безопасность в порядке, но моральный климат упал.', scoreChange: 30 })
+                    }
+                ],
+                defaultMessage: 'Выберите меру воздействия на нарушителя.'
+            };
+        }
+        return null;
+    }
+
+    function resetGame() {
+        currentScene = 1;
+        score = 0;
+        gameActive = true;
+        finalMessage = "";
+        waitingForNext = false;
+        render();
+    }
+
+    render();
+</script>
+</body>
+</html>