|
|
|
|
document.getElementById("fileInput").addEventListener("change", handleFile, false);
|
|
|
|
|
document.getElementById("randomSelectButton").addEventListener("click", randomSelect);
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
consecutiveCorrect: 0,
|
|
|
|
|
consecutiveIncorrect: 0,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
// 移除按钮的 hidden 类以显示点名按钮
|
|
|
|
|
document.getElementById("randomSelectButton").classList.remove("hidden");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
reader.readAsArrayBuffer(file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 随机点名并计算积分
|
|
|
|
|
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");
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
}
|