|  |  |  | @ -0,0 +1,154 @@ | 
			
		
	
		
			
				
					|  |  |  |  | document.getElementById("fileInput").addEventListener("change", handleFile, false); | 
			
		
	
		
			
				
					|  |  |  |  | document.getElementById("randomSelectButton").addEventListener("click", randomSelect); | 
			
		
	
		
			
				
					|  |  |  |  | document.getElementById("clearScoresButton").addEventListener("click", clearScores); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | let students = []; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 处理文件上传
 | 
			
		
	
		
			
				
					|  |  |  |  | function handleFile(e) { | 
			
		
	
		
			
				
					|  |  |  |  |     const file = e.target.files[0]; | 
			
		
	
		
			
				
					|  |  |  |  |     const reader = new FileReader(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     reader.onload = function (event) { | 
			
		
	
		
			
				
					|  |  |  |  |         const data = new Uint8Array(event.target.result); | 
			
		
	
		
			
				
					|  |  |  |  |         const workbook = XLSX.read(data, { type: "array" }); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         const firstSheet = workbook.Sheets[workbook.SheetNames[0]]; | 
			
		
	
		
			
				
					|  |  |  |  |         const rows = XLSX.utils.sheet_to_json(firstSheet, { header: 1 }); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // 将学生数据转换为对象数组
 | 
			
		
	
		
			
				
					|  |  |  |  |         students = rows.map(row => ({ | 
			
		
	
		
			
				
					|  |  |  |  |             id: row[0], | 
			
		
	
		
			
				
					|  |  |  |  |             name: row[1], | 
			
		
	
		
			
				
					|  |  |  |  |             score: 0,  // 初始积分为0
 | 
			
		
	
		
			
				
					|  |  |  |  |             consecutiveCorrect: 0, | 
			
		
	
		
			
				
					|  |  |  |  |             consecutiveIncorrect: 0, | 
			
		
	
		
			
				
					|  |  |  |  |         })); | 
			
		
	
		
			
				
					|  |  |  |  |         students.shift(); // 删除第一行的标题
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // 加载已存储的学生积分
 | 
			
		
	
		
			
				
					|  |  |  |  |         loadSavedScores(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // 移除按钮的 hidden 类以显示点名按钮
 | 
			
		
	
		
			
				
					|  |  |  |  |         document.getElementById("randomSelectButton").classList.remove("hidden"); | 
			
		
	
		
			
				
					|  |  |  |  |         document.getElementById("clearScoresButton").classList.remove("hidden"); | 
			
		
	
		
			
				
					|  |  |  |  |     }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     reader.readAsArrayBuffer(file); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 加载本地存储的积分数据
 | 
			
		
	
		
			
				
					|  |  |  |  | function loadSavedScores() { | 
			
		
	
		
			
				
					|  |  |  |  |     const savedData = localStorage.getItem("studentsData"); | 
			
		
	
		
			
				
					|  |  |  |  |     if (savedData) { | 
			
		
	
		
			
				
					|  |  |  |  |         const savedStudents = JSON.parse(savedData); | 
			
		
	
		
			
				
					|  |  |  |  |         students.forEach(student => { | 
			
		
	
		
			
				
					|  |  |  |  |             const savedStudent = savedStudents.find(s => s.id === student.id); | 
			
		
	
		
			
				
					|  |  |  |  |             if (savedStudent) { | 
			
		
	
		
			
				
					|  |  |  |  |                 student.score = savedStudent.score; | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     updateRanking(); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 保存积分数据到本地存储
 | 
			
		
	
		
			
				
					|  |  |  |  | function saveScores() { | 
			
		
	
		
			
				
					|  |  |  |  |     localStorage.setItem("studentsData", JSON.stringify(students)); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 随机点名并计算积分
 | 
			
		
	
		
			
				
					|  |  |  |  | function randomSelect() { | 
			
		
	
		
			
				
					|  |  |  |  |     if (students.length === 0) return; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 计算总积分,按比例降低被点到的概率
 | 
			
		
	
		
			
				
					|  |  |  |  |     const totalScore = students.reduce((acc, student) => acc + (1 / (student.score + 1)), 0); | 
			
		
	
		
			
				
					|  |  |  |  |     let randomValue = Math.random() * totalScore; | 
			
		
	
		
			
				
					|  |  |  |  |     let selectedStudent = null; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     for (let student of students) { | 
			
		
	
		
			
				
					|  |  |  |  |         randomValue -= 1 / (student.score + 1); | 
			
		
	
		
			
				
					|  |  |  |  |         if (randomValue <= 0) { | 
			
		
	
		
			
				
					|  |  |  |  |             selectedStudent = student; | 
			
		
	
		
			
				
					|  |  |  |  |             break; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 点到学生
 | 
			
		
	
		
			
				
					|  |  |  |  |     document.getElementById("studentInfo").innerHTML = ` | 
			
		
	
		
			
				
					|  |  |  |  |         <p>点到学生:${selectedStudent.name} (学号: ${selectedStudent.id})</p> | 
			
		
	
		
			
				
					|  |  |  |  |     `;
 | 
			
		
	
		
			
				
					|  |  |  |  |     document.getElementById("studentInfo").classList.remove("hidden"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 积分逻辑:每点到一次,积分 +1
 | 
			
		
	
		
			
				
					|  |  |  |  |     selectedStudent.score += 1; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 模拟回答是否正确
 | 
			
		
	
		
			
				
					|  |  |  |  |     const isAnswerCorrect = Math.random() > 0.5; // 随机决定答案是否正确
 | 
			
		
	
		
			
				
					|  |  |  |  |     let answerScore = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 答题逻辑
 | 
			
		
	
		
			
				
					|  |  |  |  |     if (isAnswerCorrect) { | 
			
		
	
		
			
				
					|  |  |  |  |         answerScore = Math.random() * 2 + 0.5; // 随机增加0.5到2.5分
 | 
			
		
	
		
			
				
					|  |  |  |  |         selectedStudent.score += answerScore; // 增加答对的分数
 | 
			
		
	
		
			
				
					|  |  |  |  |         selectedStudent.consecutiveCorrect += 1; // 连续正确增加计数
 | 
			
		
	
		
			
				
					|  |  |  |  |         selectedStudent.consecutiveIncorrect = 0; // 重置错误计数
 | 
			
		
	
		
			
				
					|  |  |  |  |     } else { | 
			
		
	
		
			
				
					|  |  |  |  |         answerScore = -1; // 答错则扣1分
 | 
			
		
	
		
			
				
					|  |  |  |  |         selectedStudent.score += answerScore; // 扣分
 | 
			
		
	
		
			
				
					|  |  |  |  |         selectedStudent.consecutiveIncorrect += 1; // 连续错误增加计数
 | 
			
		
	
		
			
				
					|  |  |  |  |         selectedStudent.consecutiveCorrect = 0; // 重置正确计数
 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 连续答对翻倍,连续答错扣分翻倍
 | 
			
		
	
		
			
				
					|  |  |  |  |     if (selectedStudent.consecutiveCorrect > 1) { | 
			
		
	
		
			
				
					|  |  |  |  |         selectedStudent.score += answerScore; // 连续答对,翻倍
 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     if (selectedStudent.consecutiveIncorrect > 1) { | 
			
		
	
		
			
				
					|  |  |  |  |         selectedStudent.score += answerScore; // 连续答错,翻倍
 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 显示反馈
 | 
			
		
	
		
			
				
					|  |  |  |  |     const answerFeedback = isAnswerCorrect ? `+${answerScore.toFixed(1)} (答对)` : `${answerScore} (答错)`; | 
			
		
	
		
			
				
					|  |  |  |  |     document.getElementById("feedback").innerHTML = ` | 
			
		
	
		
			
				
					|  |  |  |  |         <p>${selectedStudent.name} 的积分变动:+1 (点到) ${answerFeedback}</p> | 
			
		
	
		
			
				
					|  |  |  |  |     `;
 | 
			
		
	
		
			
				
					|  |  |  |  |     document.getElementById("feedback").classList.remove("hidden"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 保存积分到本地存储
 | 
			
		
	
		
			
				
					|  |  |  |  |     saveScores(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     updateRanking(); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 更新积分排行榜
 | 
			
		
	
		
			
				
					|  |  |  |  | function updateRanking() { | 
			
		
	
		
			
				
					|  |  |  |  |     students.sort((a, b) => b.score - a.score); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     let rankTableHTML = students.map(student => ` | 
			
		
	
		
			
				
					|  |  |  |  |         <tr> | 
			
		
	
		
			
				
					|  |  |  |  |             <td>${student.id}</td> | 
			
		
	
		
			
				
					|  |  |  |  |             <td>${student.name}</td> | 
			
		
	
		
			
				
					|  |  |  |  |             <td>${student.score.toFixed(1)}</td> | 
			
		
	
		
			
				
					|  |  |  |  |         </tr> | 
			
		
	
		
			
				
					|  |  |  |  |     `).join("");
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     document.getElementById("rankList").innerHTML = rankTableHTML; | 
			
		
	
		
			
				
					|  |  |  |  |     document.getElementById("rankTable").classList.remove("hidden"); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 清除积分
 | 
			
		
	
		
			
				
					|  |  |  |  | function clearScores() { | 
			
		
	
		
			
				
					|  |  |  |  |     students.forEach(student => { | 
			
		
	
		
			
				
					|  |  |  |  |         student.score = 0; | 
			
		
	
		
			
				
					|  |  |  |  |         student.consecutiveCorrect = 0; // 清除连续正确计数
 | 
			
		
	
		
			
				
					|  |  |  |  |         student.consecutiveIncorrect = 0; // 清除连续错误计数
 | 
			
		
	
		
			
				
					|  |  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  |  |     saveScores(); // 保存清空后的数据
 | 
			
		
	
		
			
				
					|  |  |  |  |     updateRanking(); // 更新排行榜
 | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 页面加载时,加载学生数据
 | 
			
		
	
		
			
				
					|  |  |  |  | window.onload = function() { | 
			
		
	
		
			
				
					|  |  |  |  |     loadSavedScores(); | 
			
		
	
		
			
				
					|  |  |  |  | }; |