Compare commits

..

No commits in common. "800575a79c350695a73ef3a3d6b6e271d35f8019" and "0f52440946a268ce4b95e1fd5f4d0b808198b9c0" have entirely different histories.

View file

@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react';
import '../questionStyle.css'; import '../questionStyle.css';
import { Button, TextField } from '@mui/material'; import { Button, TextField } from '@mui/material';
import { FormattedTextTemplate } from '../../GiftTemplate/templates/TextTypeTemplate'; import { FormattedTextTemplate } from '../../GiftTemplate/templates/TextTypeTemplate';
import { MultipleNumericalAnswer, NumericalQuestion } from 'gift-pegjs'; import { NumericalQuestion, SimpleNumericalAnswer, RangeNumericalAnswer, HighLowNumericalAnswer } from 'gift-pegjs';
import { isSimpleNumericalAnswer, isRangeNumericalAnswer, isHighLowNumericalAnswer, isMultipleNumericalAnswer } from 'gift-pegjs/typeGuards'; import { isSimpleNumericalAnswer, isRangeNumericalAnswer, isHighLowNumericalAnswer, isMultipleNumericalAnswer } from 'gift-pegjs/typeGuards';
import { AnswerType } from 'src/pages/Student/JoinRoom/JoinRoom'; import { AnswerType } from 'src/pages/Student/JoinRoom/JoinRoom';
@ -19,151 +19,105 @@ const NumericalQuestionDisplay: React.FC<Props> = (props) => {
props; props;
const [answer, setAnswer] = useState<AnswerType>(passedAnswer || ''); const [answer, setAnswer] = useState<AnswerType>(passedAnswer || '');
const [isGoodAnswer, setisGoodAnswer] = useState<boolean>(false); const [isGoodAnswer, setisGoodAnswer] = useState<boolean>(false);
let isMultpleAnswer = false; const [isMultpleAnswer, setIsMultpleAnswer] = useState<boolean>(false);
const correctAnswers = question.choices; const correctAnswers = question.choices;
const correctAnswersList: number[] = [];
const correctAnswersPhrases: string[] = []; const correctAnswersPhrases: string[] = [];
let correctAnswer = ''; let correctAnswer = '';
useEffect(() => { useEffect(() => {
if (passedAnswer !== null && passedAnswer !== undefined) { if (passedAnswer !== null && passedAnswer !== undefined) {
setAnswer(passedAnswer); setAnswer(passedAnswer);
} }
}, [passedAnswer]); }, [passedAnswer]);
useEffect(() => { useEffect(() => {
checkAnswer(); checkAnswer();
}, [answer]); }, [answer]);
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 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 '';
};
const checkAnswer = () => { const checkAnswer = () => {
if (isMultpleAnswer) { if(isMultpleAnswer) {
correctAnswers.forEach((answers) => { correctAnswers.forEach((answers) => {
if ( if(isSimpleNumericalAnswer(answers) && answer === answers.number) {
isMultipleNumericalAnswer(answers) && setisGoodAnswer(true);
isValidWeight(answers.weight) && } else if(isRangeNumericalAnswer(answers) && answer as number >= answers.number - answers.range && answer as number <= answers.number + answers.range) {
isAnswerCorrect(answer as number, answers.answer) setisGoodAnswer(true);
) { } else if(isHighLowNumericalAnswer(answers) && answer as number >= answers.numberLow && answer as number <= answers.numberHigh) {
setisGoodAnswer(true); setisGoodAnswer(true);
} }
});
} else {
const firstAnswer = correctAnswers[0];
if (isAnswerCorrect(answer as number, firstAnswer)) {
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);
}
};
}; };
if (isMultipleNumericalAnswer(correctAnswers[0])) { //const isSingleAnswer = correctAnswers.length === 1;
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);
correctAnswers.forEach((answers) => { correctAnswers.forEach((answers) => {
if ( if(isSimpleNumericalAnswer(answers)) {
isMultipleNumericalAnswer(answers) && correctAnswersPhrases.push(`${(answers as SimpleNumericalAnswer).number}`);
isValidWeight(answers.weight) } else if(isRangeNumericalAnswer(answers)) {
) { correctAnswersPhrases.push(`Entre ${answers.number - answers.range} et ${answers.number + answers.range}`);
correctAnswersPhrases.push(formatCorrectAnswer(answers.answer)); } else if(isHighLowNumericalAnswer(answers)) {
correctAnswersPhrases.push(`Entre ${answers.numberLow} et ${answers.numberHigh}`);
} }
}); });
isMultpleAnswer = true; }
} else { else {
correctAnswer = formatCorrectAnswer(correctAnswers[0]); throw new Error('Unknown numerical answer type');
} }
return ( return (
<div className="question-wrapper"> <div className="question-wrapper">
{showAnswer && ( {showAnswer && (
<div> <div>
<div className='question-feedback-validation'> <div className='question-feedback-validation'>
{isGoodAnswer ? '✅ Correct! ' : '❌ Incorrect!'} {isGoodAnswer ? '✅ Correct! ' : '❌ Incorrect!'}
</div>
<div className="question-title">
Question :
</div>
</div> </div>
<div className="question-title">
Question :
</div>
</div>
)} )}
<div> <div>
<div dangerouslySetInnerHTML={{ __html: FormattedTextTemplate(question.formattedStem) }} /> <div dangerouslySetInnerHTML={{ __html: FormattedTextTemplate(question.formattedStem) }} />
</div> </div>
{showAnswer ? ( {showAnswer ? (
<> <>
<div className="correct-answer-text mb-1"> <div className="correct-answer-text mb-1">
<div> <div>
<div className="question-title"> <div className="question-title">
Réponse(s) accepté(es): Réponse(s) accepté(es):
</div> </div>
{isMultpleAnswer ? ( <div className="accepted-answers">
correctAnswersPhrases.map((phrase) => ( {correctAnswer}
<div key={phrase} className="accepted-answers"> </div>
{phrase}
</div>
))
) : (
<div className="accepted-answers">{correctAnswer}</div>
)}
</div> </div>
<div> <div>
<div className="question-title"> <div className="question-title">
Votre réponse est: </div> Votre réponse est: </div>
<span> <div className="accepted-answers">{answer}</div>
<div className="accepted-answers">{answer}</div>
{isMultpleAnswer && (() => {
const highestPriorityAnswer = correctAnswers.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, otherwise compare weights numerically
if (prevWeight === -1 && currentWeight !== -1) return prev;
if (currentWeight === -1 && prevWeight !== -1) return current;
return currentWeight > prevWeight ? current : prev;
});
return isAnswerCorrect(answer as number, (highestPriorityAnswer as MultipleNumericalAnswer).answer) && (
<div>
{(highestPriorityAnswer as MultipleNumericalAnswer).formattedFeedback && (
<div className="global-feedback">
<div
dangerouslySetInnerHTML={{
__html: FormattedTextTemplate(
(highestPriorityAnswer as MultipleNumericalAnswer).formattedFeedback!
),
}}
/>
</div>
)}
</div>
);
})()}
</span>
</div> </div>
</div> </div>
{question.formattedGlobalFeedback && <div className="global-feedback mb-2"> {question.formattedGlobalFeedback && <div className="global-feedback mb-2">
@ -189,19 +143,19 @@ const NumericalQuestionDisplay: React.FC<Props> = (props) => {
</div> </div>
)} )}
{handleOnSubmitAnswer && ( {handleOnSubmitAnswer && (
<div className="submit-button-container"> <div className="submit-button-container">
<Button <Button
className='submit-button' className='submit-button'
variant="contained" variant="contained"
onClick={() => onClick={() =>
answer !== undefined && answer !== undefined &&
handleOnSubmitAnswer && handleOnSubmitAnswer &&
handleOnSubmitAnswer(answer) handleOnSubmitAnswer(answer)
} }
disabled={answer === "" || isNaN(answer as number)} disabled={answer === "" || isNaN(answer as number)}
> >
Répondre Répondre
</Button> </Button>
</div> </div>
)} )}
</> </>