From 459b30f63cfc9a41c08fc56bcce4f086876b54e7 Mon Sep 17 00:00:00 2001 From: JubaAzul <118773284+JubaAzul@users.noreply.github.com> Date: Fri, 21 Mar 2025 18:58:18 -0400 Subject: [PATCH] =?UTF-8?q?[FEATURE]=20Ajout=20des=20r=C3=A9troactions=20p?= =?UTF-8?q?our=20les=20questions=20=C3=A0=20choix=20multiples=20et=20r?= =?UTF-8?q?=C3=A9ponses=20courtes=20Fixes=20#291?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NumericalQuestionDisplay.tsx | 206 +++++++++++------- 1 file changed, 129 insertions(+), 77 deletions(-) diff --git a/client/src/components/QuestionsDisplay/NumericalQuestionDisplay/NumericalQuestionDisplay.tsx b/client/src/components/QuestionsDisplay/NumericalQuestionDisplay/NumericalQuestionDisplay.tsx index e415c14..f81c46a 100644 --- a/client/src/components/QuestionsDisplay/NumericalQuestionDisplay/NumericalQuestionDisplay.tsx +++ b/client/src/components/QuestionsDisplay/NumericalQuestionDisplay/NumericalQuestionDisplay.tsx @@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react'; import '../questionStyle.css'; import { Button, TextField } from '@mui/material'; import { FormattedTextTemplate } from '../../GiftTemplate/templates/TextTypeTemplate'; -import { NumericalQuestion, SimpleNumericalAnswer, RangeNumericalAnswer, HighLowNumericalAnswer } from 'gift-pegjs'; +import { MultipleNumericalAnswer, NumericalQuestion } from 'gift-pegjs'; import { isSimpleNumericalAnswer, isRangeNumericalAnswer, isHighLowNumericalAnswer, isMultipleNumericalAnswer } from 'gift-pegjs/typeGuards'; import { AnswerType } from 'src/pages/Student/JoinRoom/JoinRoom'; @@ -19,105 +19,157 @@ const NumericalQuestionDisplay: React.FC = (props) => { props; const [answer, setAnswer] = useState(passedAnswer || ''); const [isGoodAnswer, setisGoodAnswer] = useState(false); - const [isMultpleAnswer, setIsMultpleAnswer] = useState(false); - + let isMultpleAnswer = false; const correctAnswers = question.choices; - const correctAnswersList: number[] = []; const correctAnswersPhrases: string[] = []; - let correctAnswer = ''; + useEffect(() => { - if (passedAnswer !== null && passedAnswer !== undefined) { - setAnswer(passedAnswer); - } + if (passedAnswer !== null && passedAnswer !== undefined) { + setAnswer(passedAnswer); + } }, [passedAnswer]); - + useEffect(() => { checkAnswer(); }, [answer]); - const checkAnswer = () => { - if(isMultpleAnswer) { - correctAnswers.forEach((answers) => { - if(isSimpleNumericalAnswer(answers) && answer === answers.number) { - setisGoodAnswer(true); - } else if(isRangeNumericalAnswer(answers) && answer as number >= answers.number - answers.range && answer as number <= answers.number + answers.range) { - setisGoodAnswer(true); - } else if(isHighLowNumericalAnswer(answers) && answer as number >= answers.numberLow && answer as number <= answers.numberHigh) { - setisGoodAnswer(true); - } - } - ) - ; - } else { - if(isSimpleNumericalAnswer(answers) && answer === answers.number) { - setisGoodAnswer(true); - } else if(isRangeNumericalAnswer(answers) && answer as number >= answers.number - answers.range && answer as number <= answers.number + answers.range) { - setisGoodAnswer(true); - } else if(isHighLowNumericalAnswer(answers) && answer as number >= answers.numberLow && answer as number <= answers.numberHigh) { - setisGoodAnswer(true); - } - }; + const isValidWeight = (weight?: number) => weight === undefined || weight > 0; + + const isAnswerCorrect = (answer: number, correctAnswer: any): boolean => { + if (isSimpleNumericalAnswer(correctAnswer)) { + return answer === correctAnswer.number; + } else if (isRangeNumericalAnswer(correctAnswer)) { + return ( + answer >= correctAnswer.number - correctAnswer.range && + answer <= correctAnswer.number + correctAnswer.range + ); + } else if (isHighLowNumericalAnswer(correctAnswer)) { + return ( + answer >= correctAnswer.numberLow && + answer <= correctAnswer.numberHigh + ); + } + return false; }; - //const isSingleAnswer = correctAnswers.length === 1; + const formatCorrectAnswer = (correctAnswer: any): string => { + if (isSimpleNumericalAnswer(correctAnswer)) { + return `${correctAnswer.number}`; + } else if (isRangeNumericalAnswer(correctAnswer)) { + return `Entre ${correctAnswer.number - correctAnswer.range} et ${correctAnswer.number + correctAnswer.range}`; + } else if (isHighLowNumericalAnswer(correctAnswer)) { + return `Entre ${correctAnswer.numberLow} et ${correctAnswer.numberHigh}`; + } + return ''; + }; - if (isSimpleNumericalAnswer(correctAnswers[0])) { - correctAnswer = `${(correctAnswers[0] as SimpleNumericalAnswer).number}`; - } else if (isRangeNumericalAnswer(correctAnswers[0])) { - const choice = correctAnswers[0] as RangeNumericalAnswer; - correctAnswer = `Entre ${choice.number - choice.range} et ${choice.number + choice.range}`; - } else if (isHighLowNumericalAnswer(correctAnswers[0])) { - const choice = correctAnswers[0] as HighLowNumericalAnswer; - correctAnswer = `Entre ${choice.numberLow} et ${choice.numberHigh}`; - } else if (isMultipleNumericalAnswer(correctAnswers[0])) { - setIsMultpleAnswer(true); + const checkAnswer = () => { + if (isMultpleAnswer) { + correctAnswers.forEach((answers) => { + if ( + isMultipleNumericalAnswer(answers) && + isValidWeight(answers.weight) && + isAnswerCorrect(answer as number, answers.answer) + ) { + setisGoodAnswer(true); + } + }); + } else { + const firstAnswer = correctAnswers[0]; + if (isAnswerCorrect(answer as number, firstAnswer)) { + setisGoodAnswer(true); + } + } + }; + + if (isMultipleNumericalAnswer(correctAnswers[0])) { correctAnswers.forEach((answers) => { - if(isSimpleNumericalAnswer(answers)) { - correctAnswersPhrases.push(`${(answers as SimpleNumericalAnswer).number}`); - } else if(isRangeNumericalAnswer(answers)) { - correctAnswersPhrases.push(`Entre ${answers.number - answers.range} et ${answers.number + answers.range}`); - } else if(isHighLowNumericalAnswer(answers)) { - correctAnswersPhrases.push(`Entre ${answers.numberLow} et ${answers.numberHigh}`); + if ( + isMultipleNumericalAnswer(answers) && + isValidWeight(answers.weight) + ) { + correctAnswersPhrases.push(formatCorrectAnswer(answers.answer)); } }); - } - else { - throw new Error('Unknown numerical answer type'); + isMultpleAnswer = true; + } else { + correctAnswer = formatCorrectAnswer(correctAnswers[0]); } return (
{showAnswer && ( -
-
- {isGoodAnswer ? '✅ Correct! ' : '❌ Incorrect!'} +
+
+ {isGoodAnswer ? '✅ Correct! ' : '❌ Incorrect!'} +
+
+ Question : +
+
-
- Question : -
- -
)}
{showAnswer ? ( - <> + <>
Réponse(s) accepté(es):
-
- {correctAnswer} -
+ {isMultpleAnswer ? ( + correctAnswersPhrases.map((phrase) => ( +
+ {phrase} +
+ )) + ) : ( +
{correctAnswer}
+ )}
Votre réponse est:
-
{answer}
+ +
{answer}
+ {isMultpleAnswer && (() => { + const highestPriorityAnswer = correctAnswers + .filter((correctAnswer) => + isAnswerCorrect(answer as number, (correctAnswer as MultipleNumericalAnswer).answer) + ) // Filter answers that return true for isAnswerCorrect + .reduce((prev, current) => { + const prevWeight = (prev as MultipleNumericalAnswer).weight ?? -1; // Treat undefined as highest priority + const currentWeight = (current as MultipleNumericalAnswer).weight ?? -1; // Treat undefined as highest priority + + // Prioritize undefined weights + if (prevWeight === -1 && currentWeight !== -1) return prev; + if (currentWeight === -1 && prevWeight !== -1) return current; + + // Otherwise, return the one with the smallest weight + return currentWeight < prevWeight ? current : prev; + }); + + return isAnswerCorrect(answer as number, (highestPriorityAnswer as MultipleNumericalAnswer).answer) && ( +
+ {(highestPriorityAnswer as MultipleNumericalAnswer).formattedFeedback && ( +
+
+
+ )} +
+ ); + })()} +
{question.formattedGlobalFeedback &&
@@ -143,19 +195,19 @@ const NumericalQuestionDisplay: React.FC = (props) => {
)} {handleOnSubmitAnswer && ( -
- +
+
)}