|
|
|
|
import React, { useState } from 'react';
|
|
|
|
|
import './App.css'; // 确保你有样式文件
|
|
|
|
|
|
|
|
|
|
// 学生列表组件
|
|
|
|
|
const StudentList = ({ students }) => (
|
|
|
|
|
<ul>
|
|
|
|
|
{students.map((student, index) => (
|
|
|
|
|
<li key={index}>
|
|
|
|
|
{student.name} - 积分: {student.points}
|
|
|
|
|
</li>
|
|
|
|
|
))}
|
|
|
|
|
</ul>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 随机选择组件
|
|
|
|
|
const RandomSelector = ({ students, onSelect }) => {
|
|
|
|
|
const selectRandomStudent = () => {
|
|
|
|
|
if (students.length === 0) return;
|
|
|
|
|
|
|
|
|
|
// 根据积分降低被选中概率
|
|
|
|
|
const totalPoints = students.reduce((acc, student) => acc + Math.max(student.points, 0), 0);
|
|
|
|
|
const weightedStudents = students.flatMap(student => Array(Math.max(1, 10 - student.points)).fill(student));
|
|
|
|
|
const randomIndex = Math.floor(Math.random() * weightedStudents.length);
|
|
|
|
|
const selectedStudent = weightedStudents[randomIndex];
|
|
|
|
|
|
|
|
|
|
if (typeof onSelect === 'function') {
|
|
|
|
|
onSelect(selectedStudent);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<button onClick={selectRandomStudent}>随机选择学生</button>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 主应用组件
|
|
|
|
|
const App = () => {
|
|
|
|
|
const [students, setStudents] = useState([]);
|
|
|
|
|
const [isCalling, setIsCalling] = useState(false);
|
|
|
|
|
const [selectedStudent, setSelectedStudent] = useState(null);
|
|
|
|
|
const [question, setQuestion] = useState('');
|
|
|
|
|
const [answer, setAnswer] = useState('');
|
|
|
|
|
|
|
|
|
|
const handleFileUpload = (event) => {
|
|
|
|
|
const file = event.target.files[0];
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
|
|
|
|
|
reader.onload = (e) => {
|
|
|
|
|
const text = e.target.result;
|
|
|
|
|
try {
|
|
|
|
|
const importedStudents = JSON.parse(text);
|
|
|
|
|
if (Array.isArray(importedStudents) && importedStudents.every(student => student.name)) {
|
|
|
|
|
const studentsWithPoints = importedStudents.map(student => ({ ...student, points: 0 }));
|
|
|
|
|
setStudents(studentsWithPoints);
|
|
|
|
|
} else {
|
|
|
|
|
alert("导入的文件格式不正确,请提供一个包含学生对象数组的 JSON 文件,每个对象应有 'name' 属性。");
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
alert("文件解析出错,请确保它是有效的 JSON 文件。");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
reader.readAsText(file);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleStartCalling = () => {
|
|
|
|
|
setIsCalling(true);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleStudentSelect = (student) => {
|
|
|
|
|
setSelectedStudent(student);
|
|
|
|
|
const updatedStudents = students.map(s =>
|
|
|
|
|
s.name === student.name ? { ...s, points: s.points + 1 } : s
|
|
|
|
|
);
|
|
|
|
|
setStudents(updatedStudents);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleAnswerSubmission = () => {
|
|
|
|
|
if (!selectedStudent) return;
|
|
|
|
|
|
|
|
|
|
const correctRepeat = answer.trim() === question.trim();
|
|
|
|
|
let pointChange = 0;
|
|
|
|
|
|
|
|
|
|
if (correctRepeat) {
|
|
|
|
|
pointChange += 0.5; // 准确重复问题
|
|
|
|
|
} else {
|
|
|
|
|
pointChange -= 1; // 未准确重复问题
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 假设根据情况准确回答问题,加分 (这里可以扩展逻辑)
|
|
|
|
|
const correctAnswer = true; // 这里假设答案是正确的
|
|
|
|
|
if (correctAnswer) {
|
|
|
|
|
pointChange += 2; // 根据情况加分
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const updatedStudents = students.map(s =>
|
|
|
|
|
s.name === selectedStudent.name ? { ...s, points: s.points + pointChange } : s
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
setStudents(updatedStudents);
|
|
|
|
|
setSelectedStudent(null);
|
|
|
|
|
setQuestion('');
|
|
|
|
|
setAnswer('');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="App">
|
|
|
|
|
<h1>课堂点名系统</h1>
|
|
|
|
|
<input type="file" accept=".json" onChange={handleFileUpload} />
|
|
|
|
|
<button onClick={handleStartCalling} disabled={students.length === 0 || isCalling}>
|
|
|
|
|
开始点名
|
|
|
|
|
</button>
|
|
|
|
|
<StudentList students={students} />
|
|
|
|
|
{isCalling && (
|
|
|
|
|
<RandomSelector students={students} onSelect={handleStudentSelect} />
|
|
|
|
|
)}
|
|
|
|
|
{selectedStudent && (
|
|
|
|
|
<div>
|
|
|
|
|
<h2>选中的学生:{selectedStudent.name}</h2>
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
placeholder="提问内容"
|
|
|
|
|
value={question}
|
|
|
|
|
onChange={(e) => setQuestion(e.target.value)}
|
|
|
|
|
/>
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
placeholder="回答内容"
|
|
|
|
|
value={answer}
|
|
|
|
|
onChange={(e) => setAnswer(e.target.value)}
|
|
|
|
|
/>
|
|
|
|
|
<button onClick={handleAnswerSubmission}>提交回答</button>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default App;
|