diff --git a/client/src/Types/StudentType.tsx b/client/src/Types/StudentType.tsx index 04848dc..b484af5 100644 --- a/client/src/Types/StudentType.tsx +++ b/client/src/Types/StudentType.tsx @@ -8,5 +8,5 @@ export interface StudentType { name: string; id: string; room?: string; - answers?: Answer[]; + answers: Answer[]; } diff --git a/client/src/__tests__/Types/StudentType.test.tsx b/client/src/__tests__/Types/StudentType.test.tsx index a7830d0..4e7c849 100644 --- a/client/src/__tests__/Types/StudentType.test.tsx +++ b/client/src/__tests__/Types/StudentType.test.tsx @@ -1,15 +1,17 @@ //StudentType.test.tsx -import { StudentType } from "../../Types/StudentType"; +import { StudentType, Answer } from "../../Types/StudentType"; const user : StudentType = { name: 'Student', - id: '123' + id: '123', + answers: new Array() } describe('StudentType', () => { - test('creates a student with name and id', () => { + test('creates a student with name, id and answers', () => { expect(user.name).toBe('Student'); expect(user.id).toBe('123'); + expect(user.answers.length).toBe(0); }); }); diff --git a/client/src/__tests__/components/StudentWaitPage/StudentWaitPage.test.tsx b/client/src/__tests__/components/StudentWaitPage/StudentWaitPage.test.tsx index 40fd745..c5c8dad 100644 --- a/client/src/__tests__/components/StudentWaitPage/StudentWaitPage.test.tsx +++ b/client/src/__tests__/components/StudentWaitPage/StudentWaitPage.test.tsx @@ -2,16 +2,17 @@ import { render, screen, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom'; import StudentWaitPage from '../../../components/StudentWaitPage/StudentWaitPage'; +import { StudentType, Answer } from '../../../Types/StudentType'; describe('StudentWaitPage Component', () => { - const mockUsers = [ - { id: '1', name: 'User1' }, - { id: '2', name: 'User2' }, - { id: '3', name: 'User3' }, + const mockUsers: StudentType[] = [ + { id: '1', name: 'User1', answers: new Array() }, + { id: '2', name: 'User2', answers: new Array() }, + { id: '3', name: 'User3', answers: new Array() }, ]; const mockProps = { - users: mockUsers, + students: mockUsers, launchQuiz: jest.fn(), roomName: 'Test Room', setQuizMode: jest.fn(), diff --git a/client/src/components/LiveResults/LiveResults.tsx b/client/src/components/LiveResults/LiveResults.tsx index 67e2927..ee9dca1 100644 --- a/client/src/components/LiveResults/LiveResults.tsx +++ b/client/src/components/LiveResults/LiveResults.tsx @@ -19,7 +19,7 @@ import { TableHead, TableRow } from '@mui/material'; -import { StudentType } from '../../Types/StudentType'; +import { StudentType, Answer } from '../../Types/StudentType'; import { formatLatex } from '../GiftTemplate/templates/TextType'; interface LiveResultsProps { @@ -27,50 +27,53 @@ interface LiveResultsProps { questions: QuestionType[]; showSelectedQuestion: (index: number) => void; quizMode: 'teacher' | 'student'; - students: StudentType[] + connectedStudents: StudentType[] } -interface Answer { - answer: string | number | boolean; - isCorrect: boolean; - idQuestion: number; -} +// interface Answer { +// answer: string | number | boolean; +// isCorrect: boolean; +// idQuestion: number; +// } -interface StudentResult { - username: string; - idUser: string; - answers: Answer[]; -} +// interface StudentResult { +// username: string; +// idUser: string; +// answers: Answer[]; +// } -const LiveResults: React.FC = ({ socket, questions, showSelectedQuestion, students }) => { +const LiveResults: React.FC = ({ socket, questions, showSelectedQuestion, connectedStudents }) => { const [showUsernames, setShowUsernames] = useState(false); const [showCorrectAnswers, setShowCorrectAnswers] = useState(false); - const [studentResultsMap, setStudentResultsMap] = useState>(new Map()); + const [students, setStudents] = useState(connectedStudents); + // const [studentResultsMap, setStudentResultsMap] = useState>(new Map()); const maxQuestions = questions.length; - useEffect(() => { - // Initialize the map with the current students - const newStudentResultsMap = new Map(); + // 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: [] }); - } + // for (const student of students) { + // newStudentResultsMap.set(student.id, { username: student.name, idUser: student.id, answers: [] }); + // } - setStudentResultsMap(newStudentResultsMap); - }, []) + // setStudentResultsMap(newStudentResultsMap); + // }, []) // update when students change + // useEffect(() => { + // // studentResultsMap is inconsistent with students -- need to update + + // for (const student of students as StudentType[]) { + // } + + // }, [students]) useEffect(() => { - // studentResultsMap is inconsistent with students -- need to update + // Update the students state when the initialStudents prop changes + setStudents(connectedStudents); + }, [connectedStudents]); - for (const student of students as StudentType[]) { - if (!studentResultsMap.has(student.id)) { - studentResultsMap.set(student.id, { username: student.name, idUser: student.id, answers: [] }); - } - } - - }, [students]) useEffect(() => { if (socket) { @@ -84,35 +87,19 @@ const LiveResults: React.FC = ({ socket, questions, showSelect answer: string | number | boolean; idQuestion: number; }) => { - // Update the student results in the map with the answer - setStudentResultsMap((currentResults) => { - const studentResult = currentResults.get(idUser); - if (!studentResult) { - return currentResults; - } + // make a copy of the students array so we can update it + const updatedStudents = [...students]; - const isCorrect = checkIfIsCorrect(answer, idQuestion); - studentResult.answers.push({ answer, isCorrect, idQuestion }); - return new Map(currentResults).set(idUser, studentResult); - }); + 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 + return; + } - - // setStudentResults((currentResults) => { - // const userIndex = currentResults.findIndex( - // (result) => result.idUser === idUser - // ); - // const isCorrect = checkIfIsCorrect(answer, idQuestion); - // if (userIndex !== -1) { - // const newResults = [...currentResults]; - // newResults[userIndex].answers.push({ answer, isCorrect, idQuestion }); - // return newResults; - // } else { - // return [ - // ...currentResults, - // { idUser, username, answers: [{ answer, isCorrect, idQuestion }] } - // ]; - // } - // }); + const isCorrect = checkIfIsCorrect(answer, idQuestion); + const newAnswer: Answer = { answer, isCorrect, idQuestion }; + student.answers.push(newAnswer); + setStudents(updatedStudents); // update the state }; socket.on('submit-answer', submitAnswerHandler); @@ -122,7 +109,7 @@ const LiveResults: React.FC = ({ socket, questions, showSelect } }, [socket]); - const getStudentGrade = (student: StudentResult): number => { + const getStudentGrade = (student: StudentType): number => { if (student.answers.length === 0) { return 0; } @@ -147,25 +134,22 @@ const LiveResults: React.FC = ({ socket, questions, showSelect const classAverage: number = useMemo(() => { let classTotal = 0; - - const studentResults = Array.from(studentResultsMap.values()); - studentResults.forEach((student) => { + students.forEach((student) => { classTotal += getStudentGrade(student); }); - return classTotal / studentResults.length; - }, [studentResultsMap]); + return classTotal / students.length; + }, [students]); const getCorrectAnswersPerQuestion = (index: number): number => { return ( - (Array.from(studentResultsMap.values()).filter((student) => + (students.filter((student) => student.answers.some( (answer) => parseInt(answer.idQuestion.toString()) === index + 1 && answer.isCorrect ) - ).length / studentResultsMap.size) * - 100 + ).length / students.length) * 100 ); }; @@ -314,8 +298,8 @@ const LiveResults: React.FC = ({ socket, questions, showSelect - {Array.from(studentResultsMap.values()).map((student) => ( - + {students.map((student) => ( + = ({ socket, questions, showSelect }} >
- {showUsernames ? student.username : '******'} + {showUsernames ? student.name : '******'}
{Array.from({ length: maxQuestions }, (_, index) => { @@ -396,7 +380,7 @@ const LiveResults: React.FC = ({ socket, questions, showSelect color: 'rgba(0, 0, 0)' }} > - {studentResultsMap.size > 0 + {students.length > 0 ? `${getCorrectAnswersPerQuestion(index).toFixed()} %` : '-'} @@ -412,7 +396,7 @@ const LiveResults: React.FC = ({ socket, questions, showSelect color: 'rgba(0, 0, 0)' }} > - {studentResultsMap.size > 0 ? `${classAverage.toFixed()} %` : '-'} + {students.length > 0 ? `${classAverage.toFixed()} %` : '-'}
diff --git a/client/src/components/StudentWaitPage/StudentWaitPage.tsx b/client/src/components/StudentWaitPage/StudentWaitPage.tsx index 5bfc6a2..5937f08 100644 --- a/client/src/components/StudentWaitPage/StudentWaitPage.tsx +++ b/client/src/components/StudentWaitPage/StudentWaitPage.tsx @@ -1,4 +1,4 @@ -import { Button, Chip, Grid } from '@mui/material'; +import { Box, Button, Chip } from '@mui/material'; import { StudentType } from '../../Types/StudentType'; import { PlayArrow } from '@mui/icons-material'; import LaunchQuizDialog from '../LaunchQuizDialog/LaunchQuizDialog'; @@ -6,12 +6,12 @@ import { useState } from 'react'; import './studentWaitPage.css'; interface Props { - users: StudentType[]; + students: StudentType[]; launchQuiz: () => void; setQuizMode: (mode: 'student' | 'teacher') => void; } -const StudentWaitPage: React.FC = ({ users, launchQuiz, setQuizMode }) => { +const StudentWaitPage: React.FC = ({ students, launchQuiz, setQuizMode }) => { const [isDialogOpen, setIsDialogOpen] = useState(false); return ( @@ -30,15 +30,15 @@ const StudentWaitPage: React.FC = ({ users, launchQuiz, setQuizMode }) =>
- + - {users.map((user, index) => ( - - - + {students.map((student, index) => ( + + + ))} - +
diff --git a/client/src/pages/Teacher/ManageRoom/ManageRoom.tsx b/client/src/pages/Teacher/ManageRoom/ManageRoom.tsx index 0691d9c..8c96580 100644 --- a/client/src/pages/Teacher/ManageRoom/ManageRoom.tsx +++ b/client/src/pages/Teacher/ManageRoom/ManageRoom.tsx @@ -74,7 +74,7 @@ const ManageRoom: React.FC = () => { setSocket(null); setQuizQuestions(undefined); setCurrentQuestion(undefined); - setStudents([]); + setStudents(new Array()); setRoomName(''); } }; @@ -293,7 +293,7 @@ const ManageRoom: React.FC = () => { socket={socket} questions={quizQuestions} showSelectedQuestion={showSelectedQuestion} - students={students} + connectedStudents={students} > @@ -312,7 +312,7 @@ const ManageRoom: React.FC = () => { ) : ( diff --git a/server/socket/socket.js b/server/socket/socket.js index 0d63ab2..dc7e99f 100644 --- a/server/socket/socket.js +++ b/server/socket/socket.js @@ -49,10 +49,15 @@ const setupWebsocket = (io) => { io.sockets.adapter.rooms.get(enteredRoomName).size; if (clientsInRoom <= MAX_USERS_PER_ROOM) { + const newStudent = { + id: socket.id, + name: username, + answers: [], + }; socket.join(enteredRoomName); socket .to(enteredRoomName) - .emit("user-joined", { name: username, id: socket.id }); + .emit("user-joined", newStudent); socket.emit("join-success"); } else { socket.emit("join-failure", "La salle est remplie");