// LiveResults.tsx import React, { useMemo, useState } from 'react'; import { Socket } from 'socket.io-client'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faCheck, faCircleXmark } from '@fortawesome/free-solid-svg-icons'; import { QuestionType } from '../../Types/QuestionType'; import './liveResult.css'; import { FormControlLabel, FormGroup, Paper, Switch, Table, TableBody, TableCell, TableContainer, TableFooter, TableHead, TableRow } from '@mui/material'; import { StudentType } from '../../Types/StudentType'; import { formatLatex } from '../GiftTemplate/templates/TextType'; interface LiveResultsProps { socket: Socket | null; questions: QuestionType[]; showSelectedQuestion: (index: number) => void; quizMode: 'teacher' | 'student'; students: StudentType[] } // interface Answer { // answer: string | number | boolean; // isCorrect: boolean; // idQuestion: number; // } // interface StudentResult { // username: string; // idUser: string; // answers: Answer[]; // } const LiveResults: React.FC = ({ questions, showSelectedQuestion, students }) => { const [showUsernames, setShowUsernames] = useState(false); const [showCorrectAnswers, setShowCorrectAnswers] = useState(false); // const [students, setStudents] = useState(initialStudents); // const [studentResultsMap, setStudentResultsMap] = useState>(new Map()); const maxQuestions = questions.length; // useEffect(() => { // // Initialize the map with the current students // const newStudentResultsMap = new Map(); // for (const student of students) { // newStudentResultsMap.set(student.id, { username: student.name, idUser: student.id, answers: [] }); // } // setStudentResultsMap(newStudentResultsMap); // }, []) // update when students change // useEffect(() => { // // studentResultsMap is inconsistent with students -- need to update // for (const student of students as StudentType[]) { // } // }, [students]) // useEffect(() => { // if (socket) { // const submitAnswerHandler = ({ // idUser, // answer, // idQuestion // }: { // idUser: string; // username: string; // answer: string | number | boolean; // idQuestion: number; // }) => { // console.log(`Received answer from ${idUser} for question ${idQuestion}: ${answer}`); // // print the list of current student names // console.log('Current students:'); // students.forEach((student) => { // console.log(student.name); // }); // // Update the students state using the functional form of setStudents // setStudents((prevStudents) => { // let foundStudent = false; // const updatedStudents = prevStudents.map((student) => { // if (student.id === idUser) { // foundStudent = true; // const updatedAnswers = student.answers.map((ans) => { // const newAnswer: Answer = { answer, isCorrect: checkIfIsCorrect(answer, idQuestion), idQuestion }; // console.log(`Updating answer for ${student.name} for question ${idQuestion} to ${answer}`); // return (ans.idQuestion === idQuestion ? { ...ans, newAnswer } : ans); // } // ); // return { ...student, answers: updatedAnswers }; // } // return student; // }); // if (!foundStudent) { // console.log(`Student ${idUser} not found in the list of students in LiveResults`); // } // return updatedStudents; // }); // // make a copy of the students array so we can update it // // const updatedStudents = [...students]; // // const student = updatedStudents.find((student) => student.id === idUser); // // if (!student) { // // // this is a bad thing if an answer was submitted but the student isn't in the list // // console.log(`Student ${idUser} not found in the list of students in LiveResults`); // // return; // // } // // const isCorrect = checkIfIsCorrect(answer, idQuestion); // // const newAnswer: Answer = { answer, isCorrect, idQuestion }; // // student.answers.push(newAnswer); // // // print list of answers // // console.log('Answers:'); // // student.answers.forEach((answer) => { // // console.log(answer.answer); // // }); // // setStudents(updatedStudents); // update the state // }; // socket.on('submit-answer', submitAnswerHandler); // return () => { // socket.off('submit-answer'); // }; // } // }, [socket]); const getStudentGrade = (student: StudentType): number => { if (student.answers.length === 0) { return 0; } const uniqueQuestions = new Set(); let correctAnswers = 0; for (const answer of student.answers) { const { idQuestion, isCorrect } = answer; if (!uniqueQuestions.has(idQuestion)) { uniqueQuestions.add(idQuestion); if (isCorrect) { correctAnswers++; } } } return (correctAnswers / questions.length) * 100; }; const classAverage: number = useMemo(() => { let classTotal = 0; students.forEach((student) => { classTotal += getStudentGrade(student); }); return classTotal / students.length; }, [students]); const getCorrectAnswersPerQuestion = (index: number): number => { return ( (students.filter((student) => student.answers.some( (answer) => parseInt(answer.idQuestion.toString()) === index + 1 && answer.isCorrect ) ).length / students.length) * 100 ); }; // (studentResults.filter((student) => // student.answers.some( // (answer) => // parseInt(answer.idQuestion.toString()) === index + 1 && answer.isCorrect // ) // ).length / // studentResults.length) * // 100 // ); // }; // function checkIfIsCorrect(answer: string | number | boolean, idQuestion: number): boolean { // const questionInfo = questions.find((q) => // q.question.id ? q.question.id === idQuestion.toString() : false // ) as QuestionType | undefined; // const answerText = answer.toString(); // if (questionInfo) { // const question = questionInfo.question as GIFTQuestion; // if (question.type === 'TF') { // return ( // (question.isTrue && answerText == 'true') || // (!question.isTrue && answerText == 'false') // ); // } else if (question.type === 'MC') { // return question.choices.some( // (choice) => choice.isCorrect && choice.text.text === answerText // ); // } else if (question.type === 'Numerical') { // if (question.choices && !Array.isArray(question.choices)) { // if ( // question.choices.type === 'high-low' && // question.choices.numberHigh && // question.choices.numberLow // ) { // const answerNumber = parseFloat(answerText); // if (!isNaN(answerNumber)) { // return ( // answerNumber <= question.choices.numberHigh && // answerNumber >= question.choices.numberLow // ); // } // } // } // if (question.choices && Array.isArray(question.choices)) { // if ( // question.choices[0].text.type === 'range' && // question.choices[0].text.number && // question.choices[0].text.range // ) { // const answerNumber = parseFloat(answerText); // const range = question.choices[0].text.range; // const correctAnswer = question.choices[0].text.number; // if (!isNaN(answerNumber)) { // return ( // answerNumber <= correctAnswer + range && // answerNumber >= correctAnswer - range // ); // } // } // if ( // question.choices[0].text.type === 'simple' && // question.choices[0].text.number // ) { // const answerNumber = parseFloat(answerText); // if (!isNaN(answerNumber)) { // return answerNumber === question.choices[0].text.number; // } // } // } // } else if (question.type === 'Short') { // return question.choices.some( // (choice) => choice.text.text.toUpperCase() === answerText.toUpperCase() // ); // } // } // return false; // } return (
Résultats du quiz
Afficher les noms
} control={ ) => setShowUsernames(e.target.checked) } /> } /> Afficher les réponses
} control={ ) => setShowCorrectAnswers(e.target.checked) } /> } />
Nom d'utilisateur
{Array.from({ length: maxQuestions }, (_, index) => ( showSelectedQuestion(index)} >
{`Q${index + 1}`}
))}
% réussite
{students.map((student) => (
{showUsernames ? student.name : '******'}
{Array.from({ length: maxQuestions }, (_, index) => { const answer = student.answers.find( (answer) => parseInt(answer.idQuestion.toString()) === index + 1 ); const answerText = answer ? answer.answer.toString() : ''; const isCorrect = answer ? answer.isCorrect : false; return ( {showCorrectAnswers ? (
{formatLatex(answerText)}
) : isCorrect ? ( ) : ( answerText !== '' && ( ) )}
); })} {getStudentGrade(student).toFixed()} %
))}
% réussite
{Array.from({ length: maxQuestions }, (_, index) => ( {students.length > 0 ? `${getCorrectAnswersPerQuestion(index).toFixed()} %` : '-'} ))} {students.length > 0 ? `${classAverage.toFixed()} %` : '-'}
); }; export default LiveResults;