296 lines
12 KiB
JavaScript
296 lines
12 KiB
JavaScript
// 物理测验系统完整实现
|
||
const physicsQuestions = {
|
||
easy: [
|
||
{
|
||
question: "下列哪个是矢量?",
|
||
options: ["质量", "温度", "速度", "时间"],
|
||
correctAnswer: "C",
|
||
explanation: "矢量具有大小和方向,速度是矢量;质量、温度和时间是标量,只有大小没有方向。"
|
||
},
|
||
{
|
||
question: "牛顿第一定律又称为?",
|
||
options: ["惯性定律", "加速度定律", "作用与反作用定律", "能量守恒定律"],
|
||
correctAnswer: "A",
|
||
explanation: "牛顿第一定律指出物体在不受外力作用时保持静止或匀速直线运动状态,也称为惯性定律。"
|
||
},
|
||
{
|
||
question: "力的单位是?",
|
||
options: ["焦耳", "瓦特", "牛顿", "帕斯卡"],
|
||
correctAnswer: "C",
|
||
explanation: "力的单位是牛顿(N),以物理学家艾萨克·牛顿的名字命名。"
|
||
},
|
||
{
|
||
question: "下列哪种现象是由于惯性引起的?",
|
||
options: ["苹果落地", "汽车刹车时乘客前倾", "磁铁吸引铁钉", "气球升空"],
|
||
correctAnswer: "B",
|
||
explanation: "汽车刹车时,乘客由于惯性保持原来的运动状态继续向前运动,所以会前倾。"
|
||
},
|
||
{
|
||
question: "物体的加速度与什么成正比?",
|
||
options: ["质量", "速度", "作用力", "位移"],
|
||
correctAnswer: "C",
|
||
explanation: "根据牛顿第二定律,物体的加速度与作用在它上面的合外力成正比,与物体的质量成反比。"
|
||
}
|
||
],
|
||
medium: [
|
||
{
|
||
question: "关于万有引力定律,下列说法正确的是?",
|
||
options: ["万有引力只存在于天体之间", "万有引力与物体质量成正比,与距离成反比", "万有引力的发现者是牛顿", "地球对苹果的引力大于苹果对地球的引力"],
|
||
correctAnswer: "C",
|
||
explanation: "万有引力存在于任何有质量的物体之间,A错误;万有引力与距离的平方成反比,B错误;牛顿发现了万有引力定律,C正确;物体间的引力是相互的,大小相等,D错误。"
|
||
},
|
||
{
|
||
question: "自由落体运动的加速度大小约为?",
|
||
options: ["5m/s²", "9.8m/s²", "15m/s²", "20m/s²"],
|
||
correctAnswer: "B",
|
||
explanation: "在地球表面附近,自由落体运动的加速度大小约为9.8m/s²,方向竖直向下。"
|
||
},
|
||
{
|
||
question: "平抛运动可以分解为哪两个方向的运动?",
|
||
options: ["水平方向匀速直线运动和竖直方向自由落体运动", "水平方向匀加速直线运动和竖直方向匀速直线运动", "水平方向匀速圆周运动和竖直方向自由落体运动", "水平方向匀减速直线运动和竖直方向匀加速直线运动"],
|
||
correctAnswer: "A",
|
||
explanation: "平抛运动可以分解为水平方向的匀速直线运动和竖直方向的自由落体运动,这两个方向的运动具有独立性。"
|
||
},
|
||
{
|
||
question: "质量为2kg的物体受到4N的力作用,其加速度为?",
|
||
options: ["0.5m/s²", "2m/s²", "4m/s²", "8m/s²"],
|
||
correctAnswer: "B",
|
||
explanation: "根据牛顿第二定律F=ma,加速度a=F/m=4N/2kg=2m/s²。"
|
||
},
|
||
{
|
||
question: "一物体做匀加速直线运动,初速度为2m/s,加速度为1m/s²,则3秒后的速度为?",
|
||
options: ["3m/s", "4m/s", "5m/s", "6m/s"],
|
||
correctAnswer: "C",
|
||
explanation: "根据匀加速直线运动速度公式v=v0+at,v=2m/s+1m/s²×3s=5m/s。"
|
||
}
|
||
],
|
||
hard: [
|
||
{
|
||
question: "相对论的创立者是哪位物理学家?",
|
||
options: ["牛顿", "爱因斯坦", "麦克斯韦", "玻尔"],
|
||
correctAnswer: "B",
|
||
explanation: "相对论是由阿尔伯特·爱因斯坦创立的,分为狭义相对论和广义相对论。"
|
||
},
|
||
{
|
||
question: "根据动量守恒定律,下列哪种情况动量不守恒?",
|
||
options: ["光滑水平面上两球碰撞", "粗糙水平面上两球碰撞", "匀速行驶的车厢内人与物体相对运动", "太空中两宇航员相互推离"],
|
||
correctAnswer: "B",
|
||
explanation: "动量守恒的条件是系统不受外力或所受合外力为零。粗糙水平面上的摩擦力属于外力,因此动量不守恒。"
|
||
},
|
||
{
|
||
question: "一物体在光滑斜面上从静止开始下滑,斜面倾角为30°,则其加速度大小为?(g=9.8m/s²)",
|
||
options: ["4.9m/s²", "9.8m/s²", "8.5m/s²", "5.7m/s²"],
|
||
correctAnswer: "A",
|
||
explanation: "沿斜面方向的加速度a=gsinθ=9.8m/s²×sin30°=4.9m/s²。"
|
||
},
|
||
{
|
||
question: "简谐运动的回复力与位移的关系是?",
|
||
options: ["成正比且同向", "成正比且反向", "成反比且同向", "成反比且反向"],
|
||
correctAnswer: "B",
|
||
explanation: "简谐运动的回复力F=-kx,其中k为劲度系数,负号表示回复力方向与位移方向相反,大小成正比。"
|
||
},
|
||
{
|
||
question: "两颗质量分别为m1和m2的星球,相距r,它们之间的万有引力大小为?",
|
||
options: ["Gm1m2/r", "Gm1m2/r²", "G(m1+m2)/r²", "Gm1m2²/r²"],
|
||
correctAnswer: "B",
|
||
explanation: "根据万有引力定律,两物体间的引力F=Gm1m2/r²,其中G为引力常量。"
|
||
}
|
||
]
|
||
};
|
||
|
||
// 全局变量
|
||
let currentDifficulty = 'medium';
|
||
let score = 0;
|
||
let totalQuestions = 5; // 当前只显示5道题 <-- 这里是问题所在
|
||
let userAnswers = {};
|
||
let mediaRecorder;
|
||
let audioChunks = [];
|
||
let audioBlob;
|
||
let isRecording = false;
|
||
let recordingStartTime;
|
||
let recordingTimer;
|
||
|
||
// DOM元素
|
||
const questionContainer = document.getElementById('question-container');
|
||
const scoreElement = document.getElementById('score');
|
||
const submitButton = document.getElementById('submit-btn');
|
||
const difficultySelect = document.getElementById('difficulty-select');
|
||
const xuebanBtn = document.getElementById('xueban-btn');
|
||
const recordButton = document.getElementById('record-btn');
|
||
const audioPlayer = document.getElementById('audio-player');
|
||
const uploadButton = document.getElementById('upload-btn');
|
||
const progressBar = document.getElementById('progress-bar');
|
||
const recordingTime = document.getElementById('recording-time');
|
||
const resultContainer = document.getElementById('result-container');
|
||
|
||
// 初始化页面
|
||
function initPage() {
|
||
renderQuestions();
|
||
submitButton.addEventListener('click', checkAnswers);
|
||
difficultySelect.addEventListener('change', changeDifficulty);
|
||
recordButton.addEventListener('click', toggleRecording);
|
||
uploadButton.addEventListener('click', uploadAudio);
|
||
|
||
// 默认隐藏学伴答疑按钮
|
||
xuebanBtn.classList.add('hidden');
|
||
}
|
||
|
||
// 获取难度名称
|
||
function getDifficultyName(difficulty) {
|
||
const names = { easy: '简单难度', medium: '中等难度', hard: '困难难度' };
|
||
return names[difficulty] || '中等难度';
|
||
}
|
||
|
||
// 渲染题目
|
||
function renderQuestions() {
|
||
questionContainer.innerHTML = '';
|
||
const questions = physicsQuestions[currentDifficulty];
|
||
|
||
// 只显示前2道题
|
||
for (let i = 0; i < totalQuestions; i++) {
|
||
const q = questions[i];
|
||
const questionElement = document.createElement('div');
|
||
questionElement.className = `question ${currentDifficulty}`;
|
||
questionElement.innerHTML = `
|
||
<h3>${getDifficultyName(currentDifficulty)} - 问题 ${i+1}</h3>
|
||
<p>${q.question}</p>
|
||
<div class="options">
|
||
${q.options.map((option, index) => `
|
||
<label class="option">
|
||
<input type="radio" name="question-${currentDifficulty}-${i}" value="${String.fromCharCode(65 + index)}">
|
||
${String.fromCharCode(65 + index)}. ${option}
|
||
</label>
|
||
`).join('')}
|
||
</div>
|
||
<div class="explanation" id="explanation-${currentDifficulty}-${i}"></div>
|
||
`;
|
||
questionContainer.appendChild(questionElement);
|
||
}
|
||
}
|
||
|
||
// 切换难度
|
||
function changeDifficulty() {
|
||
currentDifficulty = difficultySelect.value;
|
||
score = 0;
|
||
userAnswers = {};
|
||
resultContainer.innerHTML = '';
|
||
renderQuestions();
|
||
scoreElement.textContent = `得分: ${score}`;
|
||
xuebanBtn.classList.add('hidden');
|
||
}
|
||
|
||
// 检查答案
|
||
function checkAnswers() {
|
||
score = 0;
|
||
const questions = physicsQuestions[currentDifficulty];
|
||
resultContainer.innerHTML = '';
|
||
|
||
for (let i = 0; i < totalQuestions; i++) {
|
||
const q = questions[i];
|
||
const selectedOption = document.querySelector(`input[name="question-${currentDifficulty}-${i}"]:checked`);
|
||
|
||
if (selectedOption) {
|
||
userAnswers[i] = selectedOption.value;
|
||
const explanationElement = document.getElementById(`explanation-${currentDifficulty}-${i}`);
|
||
|
||
if (selectedOption.value === q.correctAnswer) {
|
||
score++;
|
||
explanationElement.className = 'explanation correct';
|
||
explanationElement.innerHTML = `<p>正确!</p><p>${q.explanation}</p>`;
|
||
} else {
|
||
explanationElement.className = 'explanation incorrect';
|
||
explanationElement.innerHTML = `<p>错误</p><p>正确答案: ${q.correctAnswer}. ${q.explanation}</p>`;
|
||
}
|
||
}
|
||
}
|
||
|
||
scoreElement.textContent = `得分: ${score}/${totalQuestions}`;
|
||
resultContainer.innerHTML += `<div class="final-result">总分: ${score}/${totalQuestions}</div>`;
|
||
|
||
// 显示学伴答疑按钮
|
||
xuebanBtn.classList.remove('hidden');
|
||
}
|
||
|
||
// 切换录音状态
|
||
async function toggleRecording() {
|
||
if (!isRecording) {
|
||
// 开始录音
|
||
try {
|
||
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||
mediaRecorder = new MediaRecorder(stream);
|
||
audioChunks = [];
|
||
|
||
mediaRecorder.ondataavailable = (e) => {
|
||
audioChunks.push(e.data);
|
||
};
|
||
|
||
mediaRecorder.onstop = () => {
|
||
audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
|
||
const audioUrl = URL.createObjectURL(audioBlob);
|
||
audioPlayer.src = audioUrl;
|
||
audioPlayer.style.display = 'block';
|
||
};
|
||
|
||
mediaRecorder.start();
|
||
isRecording = true;
|
||
recordButton.textContent = '停止录音';
|
||
recordButton.classList.add('recording');
|
||
progressBar.style.display = 'block';
|
||
recordingTime.style.display = 'block';
|
||
|
||
// 开始计时
|
||
recordingStartTime = Date.now();
|
||
updateRecordingTime();
|
||
} catch (error) {
|
||
console.error('录音初始化失败:', error);
|
||
alert('无法访问麦克风。请确保已授予麦克风权限。');
|
||
}
|
||
} else {
|
||
// 停止录音
|
||
mediaRecorder.stop();
|
||
isRecording = false;
|
||
recordButton.textContent = '开始录音';
|
||
recordButton.classList.remove('recording');
|
||
clearTimeout(recordingTimer);
|
||
|
||
// 停止所有音轨
|
||
mediaRecorder.stream.getTracks().forEach(track => track.stop());
|
||
}
|
||
}
|
||
|
||
// 更新录音时间
|
||
function updateRecordingTime() {
|
||
if (!isRecording) return;
|
||
|
||
const elapsedTime = Date.now() - recordingStartTime;
|
||
const seconds = Math.floor((elapsedTime / 1000) % 60);
|
||
const minutes = Math.floor(elapsedTime / 60000);
|
||
|
||
recordingTime.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||
progressBar.value = elapsedTime / 30000; // 30秒进度条
|
||
|
||
if (elapsedTime < 30000) { // 限制最长录音30秒
|
||
recordingTimer = setTimeout(updateRecordingTime, 1000);
|
||
} else {
|
||
toggleRecording(); // 自动停止
|
||
}
|
||
}
|
||
|
||
// 上传音频
|
||
function uploadAudio() {
|
||
if (!audioBlob) {
|
||
alert('请先录制音频');
|
||
return;
|
||
}
|
||
|
||
const formData = new FormData();
|
||
formData.append('audio', audioBlob, 'recording.wav');
|
||
|
||
// 这里是模拟上传,实际项目中替换为真实API
|
||
console.log('上传音频数据:', formData);
|
||
alert('音频上传成功! (模拟)');
|
||
}
|
||
|
||
// 页面加载完成后初始化
|
||
window.addEventListener('DOMContentLoaded', initPage);
|