{
  "case_id": "C3",
  "case_name": "划水检测学习系统",
  "prompt": "创建一个学习应用，能判断用户是\"学不会\"还是\"在划水\"，要求：\n1. 三个学习模块可选：\n   - 拼音教学\n   - 商务英语\n   - 简单数学题\n2. 检测机制：\n   - 追踪鼠标停留时间\n   - 记录答题速度\n   - 分析错误类型（粗心/不会）\n   - 监测页面切换频率\n3. 生成诊断报告：\n   - \"专注度得分\"\n   - \"知识掌握度\"\n   - \"划水指数\"\n4. 伪视频学习界面\n5. 单文件HTML",
  "result": {
    "success": true,
    "content": "这是一个单文件HTML应用，包含了你要求的所有功能。它模拟了一个在线学习平台，并在后台悄悄运行一套行为分析算法。\n\n### 使用说明\n1.  将代码保存为 `.html` 文件（例如 `learning_monitor.html`）。\n2.  用浏览器打开。\n3.  **尝试不同的行为模式**来测试算法：\n    *   **模拟划水**：在“看视频”时频繁切换到其他标签页，答题时疯狂点击（秒选），鼠标长时间不动。\n    *   **模拟学不会**：一直盯着屏幕（不切屏），答题思考很久（时间长）但最后选错。\n    *   **模拟学霸**：不切屏，答题速度适中且正确。\n\n### 源代码\n\n```html\n<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>全方位智能学习监测系统</title>\n    <style>\n        :root {\n            --bg-color: #1a1a2e;\n            --card-bg: #16213e;\n            --accent: #0f3460;\n            --highlight: #e94560;\n            --text: #f1f1f1;\n        }\n\n        body {\n            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n            background-color: var(--bg-color);\n            color: var(--text);\n            margin: 0;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            min-height: 100vh;\n        }\n\n        .container {\n            width: 800px;\n            background-color: var(--card-bg);\n            border-radius: 12px;\n            box-shadow: 0 10px 30px rgba(0,0,0,0.5);\n            overflow: hidden;\n            position: relative;\n        }\n\n        /* Header & Monitoring Badge */\n        .header {\n            padding: 20px;\n            background-color: var(--accent);\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n        }\n\n        .monitor-badge {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            font-size: 0.8em;\n            color: #ff4d4d;\n            background: rgba(255, 0, 0, 0.1);\n            padding: 5px 10px;\n            border-radius: 20px;\n            border: 1px solid rgba(255, 0, 0, 0.3);\n        }\n\n        .blink {\n            width: 8px;\n            height: 8px;\n            background-color: #ff4d4d;\n            border-radius: 50%;\n            animation: blinking 1s infinite;\n        }\n\n        @keyframes blinking {\n            0% { opacity: 1; }\n            50% { opacity: 0; }\n            100% { opacity: 1; }\n        }\n\n        /* Views */\n        .view {\n            display: none;\n            padding: 30px;\n        }\n\n        .view.active {\n            display: block;\n        }\n\n        /* Menu */\n        .module-grid {\n            display: grid;\n            grid-template-columns: repeat(3, 1fr);\n            gap: 20px;\n        }\n\n        .module-card {\n            background: rgba(255,255,255,0.05);\n            padding: 20px;\n            border-radius: 8px;\n            cursor: pointer;\n            transition: 0.3s;\n            text-align: center;\n            border: 1px solid transparent;\n        }\n\n        .module-card:hover {\n            background: rgba(255,255,255,0.1);\n            border-color: var(--highlight);\n            transform: translateY(-5px);\n        }\n\n        /* Video Player Sim */\n        .video-player {\n            width: 100%;\n            height: 350px;\n            background-color: #000;\n            display: flex;\n            flex-direction: column;\n            justify-content: center;\n            align-items: center;\n            position: relative;\n            border-radius: 8px;\n            margin-bottom: 20px;\n        }\n\n        .play-btn {\n            font-size: 50px;\n            cursor: pointer;\n            color: white;\n            opacity: 0.8;\n        }\n\n        .progress-bar-bg {\n            position: absolute;\n            bottom: 0;\n            left: 0;\n            width: 100%;\n            height: 5px;\n            background: #333;\n        }\n\n        .progress-bar-fill {\n            height: 100%;\n            width: 0%;\n            background: var(--highlight);\n            transition: width 0.2s linear;\n        }\n\n        .overlay-text {\n            position: absolute;\n            top: 20px;\n            left: 20px;\n            background: rgba(0,0,0,0.7);\n            padding: 5px 10px;\n            border-radius: 4px;\n        }\n\n        /* Quiz */\n        .question-box {\n            font-size: 1.2em;\n            margin-bottom: 20px;\n        }\n\n        .options-grid {\n            display: grid;\n            gap: 10px;\n        }\n\n        .option-btn {\n            padding: 15px;\n            background: #2a2a4a;\n            border: none;\n            color: white;\n            text-align: left;\n            border-radius: 6px;\n            cursor: pointer;\n        }\n\n        .option-btn:hover {\n            background: #3a3a5a;\n        }\n\n        /* Report */\n        .report-grid {\n            display: grid;\n            grid-template-columns: 1fr 1fr;\n            gap: 20px;\n        }\n\n        .score-card {\n            background: rgba(255,255,255,0.05);\n            padding: 20px;\n            border-radius: 8px;\n            text-align: center;\n        }\n\n        .score-value {\n            font-size: 2.5em;\n            font-weight: bold;\n            margin: 10px 0;\n        }\n\n        .score-label {\n            color: #aaa;\n            font-size: 0.9em;\n        }\n\n        .diagnosis-box {\n            grid-column: span 2;\n            background: rgba(233, 69, 96, 0.1);\n            border: 1px solid var(--highlight);\n            padding: 20px;\n            border-radius: 8px;\n            margin-top: 20px;\n        }\n\n        .restart-btn {\n            margin-top: 20px;\n            padding: 10px 30px;\n            background: var(--highlight);\n            color: white;\n            border: none;\n            border-radius: 20px;\n            cursor: pointer;\n            font-size: 1em;\n            display: block;\n            margin-left: auto;\n            margin-right: auto;\n        }\n        \n        .hidden { display: none; }\n\n    </style>\n</head>\n<body>\n\n<div class=\"container\">\n    <div class=\"header\">\n        <h3>🧠 智能学习平台 v3.0</h3>\n        <div class=\"monitor-badge\">\n            <div class=\"blink\"></div>\n            <span>行为监测中</span>\n        </div>\n    </div>\n\n    <!-- 1. Menu View -->\n    <div id=\"menu-view\" class=\"view active\">\n        <h2>请选择今日学习模块</h2>\n        <p style=\"color:#aaa; margin-bottom: 20px;\">系统将实时分析您的学习状态</p>\n        <div class=\"module-grid\">\n            <div class=\"module-card\" onclick=\"app.startModule('pinyin')\">\n                <div style=\"font-size:40px\">🔤</div>\n                <h3>拼音教学</h3>\n                <p>基础发音与声调</p>\n            </div>\n            <div class=\"module-card\" onclick=\"app.startModule('english')\">\n                <div style=\"font-size:40px\">💼</div>\n                <h3>商务英语</h3>\n                <p>职场常用术语</p>\n            </div>\n            <div class=\"module-card\" onclick=\"app.startModule('math')\">\n                <div style=\"font-size:40px\">➗</div>\n                <h3>简单数学</h3>\n                <p>快速心算训练</p>\n            </div>\n        </div>\n    </div>\n\n    <!-- 2. Video Learning View -->\n    <div id=\"video-view\" class=\"view\">\n        <h2 id=\"video-title\">课程播放中...</h2>\n        <div class=\"video-player\" id=\"video-area\">\n            <div class=\"overlay-text\">正在播放: <span id=\"video-topic\"></span></div>\n            <div class=\"play-btn\">▶</div>\n            <div style=\"margin-top:10px; color:#aaa;\">请认真观看，随后进行测试</div>\n            <div class=\"progress-bar-bg\">\n                <div class=\"progress-bar-fill\" id=\"video-progress\"></div>\n            </div>\n        </div>\n        <p id=\"video-status\">请保持专注...</p>\n    </div>\n\n    <!-- 3. Quiz View -->\n    <div id=\"quiz-view\" class=\"view\">\n        <div style=\"display:flex; justify-content:space-between;\">\n            <h2>知识检测</h2>\n            <span id=\"quiz-timer\" style=\"color:var(--highlight)\">00:00</span>\n        </div>\n        <div id=\"quiz-container\">\n            <!-- Questions injected here -->\n        </div>\n    </div>\n\n    <!-- 4. Report View -->\n    <div id=\"report-view\" class=\"view\">\n        <h2>📊 学习诊断报告</h2>\n        <div class=\"report-grid\">\n            <div class=\"score-card\">\n                <div class=\"score-label\">专注度得分</div>\n                <div class=\"score-value\" id=\"score-focus\" style=\"color:#4cd137\">--</div>\n            </div>\n            <div class=\"score-card\">\n                <div class=\"score-label\">知识掌握度</div>\n                <div class=\"score-value\" id=\"score-mastery\" style=\"color:#00a8ff\">--</div>\n            </div>\n            <div class=\"score-card\">\n                <div class=\"score-label\">划水指数</div>\n                <div class=\"score-value\" id=\"score-slacking\" style=\"color:#e84118\">--</div>\n            </div>\n            <div class=\"score-card\">\n                <div class=\"score-label\">平均答题速度</div>\n                <div class=\"score-value\" id=\"score-speed\">--s</div>\n            </div>\n            \n            <div class=\"diagnosis-box\">\n                <h3>诊断结论：</h3>\n                <p id=\"final-verdict\" style=\"font-size: 1.1em; line-height: 1.6;\"></p>\n            </div>\n        </div>\n        <button class=\"restart-btn\" onclick=\"location.reload()\">返回主页</button>\n    </div>\n</div>\n\n<script>\n    // 题库数据\n    const MODULES = {\n        pinyin: {\n            title: \"汉语拼音基础\",\n            duration: 5000, // 模拟视频时长(ms)\n            questions: [\n                { q: \"单韵母 'a' 的嘴型是？\", a: [\"圆唇\", \"张大嘴\", \"扁唇\"], correct: 1 },\n                { q: \"下列哪个是翘舌音？\", a: [\"z\", \"c\", \"zh\"], correct: 2 },\n                { q: \"一声调的符号是？\", a: [\"-\", \"ˊ\", \"ˇ\"], correct: 0 }\n            ]\n        },\n        english: {\n            title: \"商务英语入门\",\n            duration: 5000,\n            questions: [\n                { q: \"ASAP 的意思是？\", a: [\"尽可能慢\", \"尽可能快\", \"永远\"], correct: 1 },\n                { q: \"CEO 是什么的缩写？\", a: [\"首席执行官\", \"首席财务官\", \"首席技术官\"], correct: 0 },\n                { q: \"FYI 代表什么？\", a: [\"For Your Information\", \"For Your Interest\", \"For Your Internet\"], correct: 0 }\n            ]\n        },\n        math: {\n            title: \"简单数学心算\",\n            duration: 5000,\n            questions: [\n                { q: \"12 x 12 = ?\", a: [\"124\", \"144\", \"164\"], correct: 1 },\n                { q: \"100 - 45 = ?\", a: [\"55\", \"65\", \"45\"], correct: 0 },\n                { q: \"15 + 27 = ?\", a: [\"32\", \"42\", \"43\"], correct: 1 }\n            ]\n        }\n    };\n\n    // 核心应用逻辑\n    const app = {\n        currentModule: null,\n        state: 'menu', // menu, video, quiz, report\n        \n        // 监测数据\n        metrics: {\n            tabSwitches: 0,\n            mouseIdleTime: 0,\n            lastMouseMove: Date.now(),\n            videoWatchTime: 0,\n            quizData: [] // { questionId, timeTaken, isCorrect, isCareless }\n        },\n        \n        timers: {\n            video: null,\n            mouse: null,\n            quizStart: null\n        },\n\n        init() {\n            this.setupMonitoring();\n        },\n\n        setupMonitoring() {\n            // 1. 监测页面切换 (Tab Visibility)\n            document.addEventListener('visibilitychange', () => {\n                if (document.hidden) {\n                    console.log(\"用户切屏了！\");\n                    this.metrics.tabSwitches++;\n                }\n            });\n\n            // 2. 监测鼠标活跃度\n            document.addEventListener('mousemove', () => {\n                this.metrics.lastMouseMove = Date.now();\n            });\n\n            // 定时检查鼠标是否静止 (每秒检查一次)\n            this.timers.mouse = setInterval(() => {\n                if (Date.now() - this.metrics.lastMouseMove > 5000) {\n                    // 超过5秒不动，视为静止\n                    this.metrics.mouseIdleTime += 1; \n                }\n            }, 1000);\n        },\n\n        switchView(viewId) {\n            document.querySelectorAll('.view').forEach(el => el.classList.remove('active'));\n            document.getElementById(viewId).classList.add('active');\n        },\n\n        startModule(moduleId) {\n            this.currentModule = MODULES[moduleId];\n            this.metrics.tabSwitches = 0;\n            this.metrics.mouseIdleTime = 0;\n            this.metrics.quizData = [];\n            \n            this.playVideo();\n        },\n\n        playVideo() {\n            this.state = 'video';\n            this.switchView('video-view');\n            document.getElementById('video-topic').innerText = this.currentModule.title;\n            document.getElementById('video-title').innerText = \"正在学习: \" + this.currentModule.title;\n\n            let progress = 0;\n            const duration = this.currentModule.duration;\n            const interval = 50;\n            const step = 100 / (duration / interval);\n\n            const bar = document.getElementById('video-progress');\n            \n            this.timers.video = setInterval(() => {\n                progress += step;\n                bar.style.width = progress + \"%\";\n                this.metrics.videoWatchTime += interval;\n\n                if (progress >= 100) {\n                    clearInterval(this.timers.video);\n                    setTimeout(() => this.startQuiz(), 500);\n                }\n            }, interval);\n        },\n\n        startQuiz() {\n            this.state = 'quiz';\n            this.switchView('quiz-view');\n            const container = document.getElementById('quiz-container');\n            container.innerHTML = '';\n\n            this.currentModule.questions.forEach((q, index) => {\n                const qDiv = document.createElement('div');\n                qDiv.className = 'question-box';\n                qDiv.innerHTML = `\n                    <p>${index + 1}. ${q.q}</p>\n                    <div class=\"options-grid\">\n                        ${q.a.map((opt, i) => `\n                            <button class=\"option-btn\" onclick=\"app.answer(${index}, ${i})\">${opt}</button>\n                        `).join('')}\n                    </div>\n                `;\n                qDiv.dataset.id = index;\n                // 初始隐藏所有题目，只显示第一题（或者这里简化为一页显示所有，但为了测速，我们做单题切换）\n                qDiv.style.display = index === 0 ? 'block' : 'none';\n                container.appendChild(qDiv);\n            });\n\n            this.timers.quizStart = Date.now();\n        },\n\n        answer(qIndex, choiceIndex) {\n            const now = Date.now();\n            const timeTaken = (now - this.timers.quizStart) / 1000; // 秒\n            const question = this.currentModule.questions[qIndex];\n            const isCorrect = (choiceIndex === question.correct);\n\n            // 记录数据\n            this.metrics.quizData.push({\n                timeTaken: timeTaken,\n                isCorrect: isCorrect,\n                // 判定粗心：如果答题非常快(<1.5s)且错了，判定为粗心/乱点\n                isCareless: !isCorrect && timeTaken < 1.5\n            });\n\n            // 下一题\n            const nextIndex = qIndex + 1;\n            const boxes = document.querySelectorAll('.question-box');\n            \n            if (nextIndex < boxes.length) {\n                boxes[qIndex].style.display = 'none';\n                boxes[nextIndex].style.display = 'block';\n                this.timers.quizStart = Date.now(); // 重置计时器\n            } else {\n                this.generateReport();\n            }\n        },\n\n        generateReport() {\n            this.switchView('report-view');\n\n            // --- 算法核心 ---\n            \n            const totalQ = this.metrics.quizData.length;\n            const correctQ = this.metrics.quizData.filter(d => d.isCorrect).length;\n            const avgSpeed = this.metrics.quizData.reduce((acc, cur) => acc + cur.timeTaken, 0) / totalQ;\n            \n            // 1. 知识掌握度 (Mastery)\n            let mastery = (correctQ / totalQ) * 100;\n\n            // 2. 划水指数 (Slacking Index)\n            // 因素：切屏次数(权重高)，鼠标静止时间，极速答错(乱点)\n            const carelessErrors = this.metrics.quizData.filter(d => d.isCareless).length;\n            let slacking = 0;\n            slacking += (this.metrics.tabSwitches * 15); // 切一次屏加15分划水\n            slacking += (carelessErrors * 20); // 乱点一次加20分\n            slacking += (this.metrics.mouseIdleTime > 10 ? 10 : 0); // 鼠标长时间不动\n            if (slacking > 100) slacking = 100;\n\n            // 3. 专注度 (Focus)\n            // 初始100，减去划水行为\n            let focus = 100 - (this.metrics.tabSwitches * 10) - (this.metrics.mouseIdleTime / 2);\n            if (focus < 0) focus = 0;\n\n            // --- 生成结论 ---\n            \n            let verdict = \"\";\n            const elVerdict = document.getElementById('final-verdict');\n\n            // 场景判断逻辑\n            if (slacking > 60) {\n                // 划水判定\n                verdict = `<strong>判定结果：你在划水！🚫</strong><br>`;\n                verdict += `系统检测到你切换页面 ${this.metrics.tabSwitches} 次，且存在秒选错误的情况。你的心思并不在学习上。`;\n                elVerdict.style.color = \"#ff4d4d\";\n            } else if (mastery < 60) {\n                // 学不会判定\n                verdict = `<strong>判定结果：真的学不会... 🤯</strong><br>`;\n                verdict += `虽然你的专注度尚可（未频繁切屏），但正确率较低。答题耗时平均 ${avgSpeed.toFixed(1)}秒，说明你有在思考，可能是基础知识薄弱，建议重新观看视频。`;\n                elVerdict.style.color = \"#ff9f43\";\n            } else {\n                // 正常/学霸\n                verdict = `<strong>判定结果：学习状态极佳！ ✅</strong><br>`;\n                verdict += `专注度高，掌握度好。继续保持！`;\n                elVerdict.style.color = \"#2ecc71\";\n            }\n\n            // 渲染数据\n            document.getElementById('score-focus').innerText = Math.round(focus);\n            document.getElementById('score-mastery').innerText = Math.round(mastery) + \"%\";\n            document.getElementById('score-slacking').innerText = Math.round(slacking);\n            document.getElementById('score-speed').innerText = avgSpeed.toFixed(1) + \"s\";\n            elVerdict.innerHTML = verdict;\n        }\n    };\n\n    // 启动\n    app.init();\n\n</script>\n</body>\n</html>\n```\n\n### 设计思路解析\n\n为了满足你关于判断“学不会”还是“在划水”的要求，我在代码中实现了以下逻辑：\n\n1.  **监测机制 (Monitoring):**\n    *   **`visibilitychange`**: 这是检测划水的核心。如果用户在播放视频或答题时切换了标签页（去回微信、看B站），`tabSwitches` 计数器会增加。\n    *   **`mousemove` & 时间戳**: 记录鼠标最后移动的时间。如果在视频播放期间鼠标超过10秒未移动（且没有切屏），可能是在发呆或人不在电脑前。\n    *   **答题计时器**: 记录每一道题从展示到点击选项的时间差。\n\n2.  **算法逻辑 (The Algorithm):**\n\n    *   **划水 (Slacking) 判定**:\n        *   **高频切屏**: 只要切屏次数多，划水指数直接飙升。\n        *   **秒选错误 (Careless Error)**: 如果答题时间小于 1.5秒 且 **选错**，系统判定为“瞎蒙/乱点”，大幅增加划水指数。\n        *   **鼠标长时间静止**: 辅助判断。\n\n    *   **学不会 (Struggling) 判定**:\n        *   **低划水指数**: 用户没有切屏，也没有乱点（答题时间正常或较长）。\n        *   **低正确率**: 尽管很认真（没切屏，思考时间长），但还是选错了。\n        *   **长耗时**: 平均答题速度慢，说明在犹豫/思考。\n\n3.  **界面设计 (UI):**\n    *   使用深色模式（Dark Mode）模拟专业的学习/编程环境。\n    *   添加了一个 **\"行为监测中\"** 的闪烁红点，给用户心理暗示（霍桑效应），增加趣味性。\n    *   **伪视频界面**: 使用进度条模拟视频播放，强制用户等待几秒钟，这是诱发“划水”行为的最佳时机（用户通常会在等待时切屏）。\n\n你可以通过不同的操作方式来验证报告的准确性。",
    "model": "gemini-3-pro-preview",
    "usage": {
      "prompt_tokens": 158,
      "completion_tokens": 7299,
      "total_tokens": 7457
    },
    "timestamp": "2025-11-19 13:27:19"
  },
  "needs_screenshot": true,
  "needs_manual_test": true
}