mirror of
https://github.com/ets-cfuhrman-pfe/EvalueTonSavoir.git
synced 2025-08-11 21:23:54 -04:00
One StudentType that also has answers
This commit is contained in:
parent
fa4b6b5bd3
commit
91fa75131a
7 changed files with 85 additions and 93 deletions
|
|
@ -8,5 +8,5 @@ export interface StudentType {
|
|||
name: string;
|
||||
id: string;
|
||||
room?: string;
|
||||
answers?: Answer[];
|
||||
answers: Answer[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Answer>()
|
||||
}
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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<Answer>() },
|
||||
{ id: '2', name: 'User2', answers: new Array<Answer>() },
|
||||
{ id: '3', name: 'User3', answers: new Array<Answer>() },
|
||||
];
|
||||
|
||||
const mockProps = {
|
||||
users: mockUsers,
|
||||
students: mockUsers,
|
||||
launchQuiz: jest.fn(),
|
||||
roomName: 'Test Room',
|
||||
setQuizMode: jest.fn(),
|
||||
|
|
|
|||
|
|
@ -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<LiveResultsProps> = ({ socket, questions, showSelectedQuestion, students }) => {
|
||||
const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelectedQuestion, connectedStudents }) => {
|
||||
const [showUsernames, setShowUsernames] = useState<boolean>(false);
|
||||
const [showCorrectAnswers, setShowCorrectAnswers] = useState<boolean>(false);
|
||||
const [studentResultsMap, setStudentResultsMap] = useState<Map<string, StudentResult>>(new Map());
|
||||
const [students, setStudents] = useState<StudentType[]>(connectedStudents);
|
||||
// const [studentResultsMap, setStudentResultsMap] = useState<Map<string, StudentResult>>(new Map());
|
||||
|
||||
const maxQuestions = questions.length;
|
||||
|
||||
useEffect(() => {
|
||||
// Initialize the map with the current students
|
||||
const newStudentResultsMap = new Map<string, StudentResult>();
|
||||
// useEffect(() => {
|
||||
// // Initialize the map with the current students
|
||||
// const newStudentResultsMap = new Map<string, StudentResult>();
|
||||
|
||||
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<LiveResultsProps> = ({ 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<LiveResultsProps> = ({ 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<LiveResultsProps> = ({ 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<LiveResultsProps> = ({ socket, questions, showSelect
|
|||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{Array.from(studentResultsMap.values()).map((student) => (
|
||||
<TableRow key={student.idUser}>
|
||||
{students.map((student) => (
|
||||
<TableRow key={student.id}>
|
||||
<TableCell
|
||||
className="sticky-column"
|
||||
sx={{
|
||||
|
|
@ -325,7 +309,7 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
|||
}}
|
||||
>
|
||||
<div className="text-base">
|
||||
{showUsernames ? student.username : '******'}
|
||||
{showUsernames ? student.name : '******'}
|
||||
</div>
|
||||
</TableCell>
|
||||
{Array.from({ length: maxQuestions }, (_, index) => {
|
||||
|
|
@ -396,7 +380,7 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
|||
color: 'rgba(0, 0, 0)'
|
||||
}}
|
||||
>
|
||||
{studentResultsMap.size > 0
|
||||
{students.length > 0
|
||||
? `${getCorrectAnswersPerQuestion(index).toFixed()} %`
|
||||
: '-'}
|
||||
</TableCell>
|
||||
|
|
@ -412,7 +396,7 @@ const LiveResults: React.FC<LiveResultsProps> = ({ socket, questions, showSelect
|
|||
color: 'rgba(0, 0, 0)'
|
||||
}}
|
||||
>
|
||||
{studentResultsMap.size > 0 ? `${classAverage.toFixed()} %` : '-'}
|
||||
{students.length > 0 ? `${classAverage.toFixed()} %` : '-'}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableFooter>
|
||||
|
|
|
|||
|
|
@ -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<Props> = ({ users, launchQuiz, setQuizMode }) => {
|
||||
const StudentWaitPage: React.FC<Props> = ({ students, launchQuiz, setQuizMode }) => {
|
||||
const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
|
|
@ -30,15 +30,15 @@ const StudentWaitPage: React.FC<Props> = ({ users, launchQuiz, setQuizMode }) =>
|
|||
|
||||
<div className="students">
|
||||
|
||||
<Grid container spacing={3}>
|
||||
<Box display="flex" flexWrap="wrap" gap={3}>
|
||||
|
||||
{users.map((user, index) => (
|
||||
<Grid item key={user.name + index}>
|
||||
<Chip label={user.name} sx={{ width: '100%' }} />
|
||||
</Grid>
|
||||
{students.map((student, index) => (
|
||||
<Box key={student.name + index} >
|
||||
<Chip label={student.name} sx={{ width: '100%' }} />
|
||||
</Box>
|
||||
))}
|
||||
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ const ManageRoom: React.FC = () => {
|
|||
setSocket(null);
|
||||
setQuizQuestions(undefined);
|
||||
setCurrentQuestion(undefined);
|
||||
setStudents([]);
|
||||
setStudents(new Array<StudentType>());
|
||||
setRoomName('');
|
||||
}
|
||||
};
|
||||
|
|
@ -293,7 +293,7 @@ const ManageRoom: React.FC = () => {
|
|||
socket={socket}
|
||||
questions={quizQuestions}
|
||||
showSelectedQuestion={showSelectedQuestion}
|
||||
students={students}
|
||||
connectedStudents={students}
|
||||
></LiveResultsComponent>
|
||||
|
||||
</div>
|
||||
|
|
@ -312,7 +312,7 @@ const ManageRoom: React.FC = () => {
|
|||
) : (
|
||||
|
||||
<StudentWaitPage
|
||||
users={students}
|
||||
students={students}
|
||||
launchQuiz={launchQuiz}
|
||||
setQuizMode={setQuizMode}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Reference in a new issue