From a853f7dddb8fb5f60025500ad85db3dbce6dc4b7 Mon Sep 17 00:00:00 2001 From: Ivan Zambrano Date: Tue, 17 Jul 2018 14:40:10 +0200 Subject: [PATCH] Apply patch from analyses/8906 --- ...multipleAnswerTrueFalseDegreeCertainty.php | 2237 +++++++++-------- main/inc/ajax/exercise.ajax.php | 1 - main/inc/lib/exercise.lib.php | 17 +- main/inc/lib/exercise_show_functions.lib.php | 51 +- 4 files changed, 1155 insertions(+), 1151 deletions(-) diff --git a/main/exercise/multipleAnswerTrueFalseDegreeCertainty.php b/main/exercise/multipleAnswerTrueFalseDegreeCertainty.php index 5b447fc202..452e83f4c5 100644 --- a/main/exercise/multipleAnswerTrueFalseDegreeCertainty.php +++ b/main/exercise/multipleAnswerTrueFalseDegreeCertainty.php @@ -1,435 +1,439 @@ -type = MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY; - $this->isContent = $this->getIsContent(); - $this->optionsTitle = [1 => 'Answers', 2 => 'DegreeOfCertaintyThatMyAnswerIsCorrect']; - $this->options = [ - 1 => 'True', - 2 => 'False', - 3 => '50%', - 4 => '60%', - 5 => '70%', - 6 => '80%', - 7 => '90%', - 8 => '100%', - ]; - } - - /** - * Redefines Question::createAnswersForm: creates the HTML form to answer the question - * @uses globals $text and $class, defined in the calling script - * @param FormValidator $form - * @throws Exception - * @throws HTML_QuickForm_Error - */ - public function createAnswersForm($form) - { - global $text, $class; - $nbAnswers = isset($_POST['nb_answers']) ? (int) $_POST['nb_answers'] : 4; - // The previous default value was 2. See task #1759. - $nbAnswers += (isset($_POST['lessAnswers']) ? -1 : (isset($_POST['moreAnswers']) ? 1 : 0)); - - $courseId = api_get_course_int_id(); - $objEx = $_SESSION['objExercise']; - $renderer = &$form->defaultRenderer(); - $defaults = []; - - $html = ''; - - // show column comment when feedback is enable - if ($objEx->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) { - $html .= ''; - } - $html .= ''; - $form->addElement('label', get_lang('Answers').'
', $html); - - $correct = 0; - $answer = null; - if (!empty($this->id)) { - $answer = new Answer($this->id); - $answer->read(); - if (count($answer->nbrAnswers) > 0 && !$form->isSubmitted()) { - $nbAnswers = $answer->nbrAnswers; - } - } - - $form->addElement('hidden', 'nb_answers'); - $boxesNames = []; - - if ($nbAnswers < 1) { - $nbAnswers = 1; - echo Display::return_message(get_lang('YouHaveToCreateAtLeastOneAnswer')); - } - - // Can be more options - $optionData = Question::readQuestionOption($this->id, $courseId); - - for ($i = 1; $i <= $nbAnswers; ++$i) { - $renderer->setElementTemplate( - '', - 'correct['.$i.']' - ); - $renderer->setElementTemplate( - '', - 'counter['.$i.']' - ); - $renderer->setElementTemplate( - '', - 'answer['.$i.']' - ); - $renderer->setElementTemplate( - '', - 'comment['.$i.']' - ); - - $answerNumber = $form->addElement('text', 'counter['.$i.']', null, 'value="'.$i.'"'); - $answerNumber->freeze(); - - if (is_object($answer)) { - $defaults['answer['.$i.']'] = $answer->answer[$i]; - $defaults['comment['.$i.']'] = $answer->comment[$i]; - $defaults['weighting['.$i.']'] = float_format($answer->weighting[$i], 1); - - $correct = $answer->correct[$i]; - $defaults['correct['.$i.']'] = $correct; - - $j = 1; - if (!empty($optionData)) { - foreach ($optionData as $id => $data) { - $form->addElement('radio', 'correct['.$i.']', null, null, $id); - $j++; - if ($j == 3) { - break; - } - } - } - } else { - $form->addElement('radio', 'correct['.$i.']', null, null, 1); - $form->addElement('radio', 'correct['.$i.']', null, null, 2); - - $defaults['answer['.$i.']'] = ''; - $defaults['comment['.$i.']'] = ''; - $defaults['correct['.$i.']'] = ''; - } - - $boxesNames[] = 'correct['.$i.']'; - $form->addElement( - 'html_editor', - 'answer['.$i.']', - null, - ['style' => 'vertical-align:middle;'], - ['ToolbarSet' => 'TestProposedAnswer', 'Width' => '100%', 'Height' => '100']); - $form->addRule('answer['.$i.']', get_lang('ThisFieldIsRequired'), 'required'); - - // show comment when feedback is enable - if ($objEx->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) { - $form->addElement('html_editor', - 'comment['.$i.']', - null, - ['style' => 'vertical-align:middle;'], - ['ToolbarSet' => 'TestProposedAnswer', 'Width' => '100%', 'Height' => '100']); - } - $form->addElement('html', ''); - } - - $form->addElement('html', '
' - .get_lang('Number') - .'' - .get_lang('True') - .'' - .get_lang('False') - .'' - .get_lang('Answer') - .''.get_lang('Comment').'
{error}
{element}
{error}
{element}
{error}
{element}
{error}
{element}
'); - $form->addElement('html', '
'); - - // 3 scores - $form->addElement('text', 'option[1]', get_lang('Correct'), ['class' => 'span1', 'value' => '1']); - $form->addElement('text', 'option[2]', get_lang('Wrong'), ['class' => 'span1', 'value' => '-0.5']); - - $form->addElement('hidden', 'option[3]', 0); - - $form->addRule('option[1]', get_lang('ThisFieldIsRequired'), 'required'); - $form->addRule('option[2]', get_lang('ThisFieldIsRequired'), 'required'); - - $form->addElement('html', ''); - $form->addElement('hidden', 'options_count', 3); - $form->addElement('html', '


'); - - //Extra values True, false, Dont known - if (!empty($this->extra)) { - $scores = explode(':', $this->extra); - if (!empty($scores)) { - for ($i = 1; $i <= 3; $i++) { - $defaults['option['.$i.']'] = $scores[$i - 1]; - } - } - } - - if ($objEx->edit_exercise_in_lp == true) { - $form->addElement('submit', 'lessAnswers', get_lang('LessAnswer'), 'class="btn minus"'); - $form->addElement('submit', 'moreAnswers', get_lang('PlusAnswer'), 'class="btn plus"'); - //$text and $class defined in calling script - $form->addElement('submit', 'submitQuestion', $text, 'class="'.$class.'"'); - } - $renderer->setElementTemplate('{element} ', 'lessAnswers'); - $renderer->setElementTemplate('{element} ', 'submitQuestion'); - $renderer->setElementTemplate('{element} ', 'moreAnswers'); - $form->addElement('html', ''); - $defaults['correct'] = $correct; - - if (!empty($this->id)) { - $form->setDefaults($defaults); - } else { - //if ($this -> isContent == 1) { - $form->setDefaults($defaults); - //} - } - $form->setConstants(['nb_answers' => $nbAnswers]); - } - - /** - * abstract function which creates the form to create / edit the answers of the question. - * - * @param FormValidator $form - * @param Exercise $exercise - */ - public function processAnswersCreation($form, $exercise) - { - $questionWeighting = 0; - $objAnswer = new Answer($this->id); - $nbAnswers = $form->getSubmitValue('nb_answers'); - - $courseId = api_get_course_int_id(); - - $correct = []; - $options = Question::readQuestionOption($this->id, $courseId); - - if (!empty($options)) { - foreach ($options as $optionData) { - $id = $optionData['id']; - unset($optionData['id']); - Question::updateQuestionOption($id, $optionData, $courseId); - } - } else { - for ($i = 1; $i <= 8; $i++) { - $lastId = Question::saveQuestionOption($this->id, $this->options[$i], $courseId, $i); - $correct[$i] = $lastId; - } - } - - /* Getting quiz_question_options (true, false, doubt) because - it's possible that there are more options in the future */ - - $newOptions = Question::readQuestionOption($this->id, $courseId); - - $sortedByPosition = []; - foreach ($newOptions as $item) { - $sortedByPosition[$item['position']] = $item; - } - - /* Saving quiz_question.extra values that has the correct scores of - the true, false, doubt options registered in this format - XX:YY:ZZZ where XX is a float score value. */ - $extraValues = []; - - for ($i = 1; $i <= 3; $i++) { - $score = trim($form->getSubmitValue('option['.$i.']')); - $extraValues[] = $score; - } - $this->setExtra(implode(':', $extraValues)); - - for ($i = 1; $i <= $nbAnswers; $i++) { - $answer = trim($form->getSubmitValue('answer['.$i.']')); - $comment = trim($form->getSubmitValue('comment['.$i.']')); - $goodAnswer = trim($form->getSubmitValue('correct['.$i.']')); - if (empty($options)) { - // If this is the first time that the question is created then change - // the default values from the form 1 and 2 by the correct "option id" registered - $goodAnswer = $sortedByPosition[$goodAnswer]['id']; - } - $questionWeighting += $extraValues[0]; //By default 0 has the correct answers - $objAnswer->createAnswer($answer, $goodAnswer, $comment, '', $i); - } - - // saves the answers into the data base - $objAnswer->save(); - - // sets the total weighting of the question - $this->updateWeighting($questionWeighting); - $this->save($exercise); - } - - /** - * Show result table headers - * @param int $feedbackType - * @param int $counter - * @param float $score - * - * @return null|string - */ - public function return_header($feedbackType = null, $counter = null, $score = null) - { - $header = parent::return_header($feedbackType, $counter, $score); - $header .= '' - ; - if ($feedbackType != EXERCISE_FEEDBACK_TYPE_EXAM) { - $header .= ''; - } else { - $header .= ''; - } - $header .= ''; - - return $header; - } - - /** - * Method to recovery color to show by precision of the student's answer. - * - * @param $studentAnwser - * @param $expectedAnswer - * @param $studentDegreeChoicePosition - * - * @return string - */ - public function getColorResponse($studentAnwser, $expectedAnswer, $studentDegreeChoicePosition) - { - $checkResult = ($studentAnwser == $expectedAnswer) ? true : false; - if ($checkResult) { - if ($studentDegreeChoicePosition >= 6) { - return '#088A08'; - } - if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { - return '#A9F5A9'; - } - if ($studentDegreeChoicePosition == 3) { - return '#FFFFFF'; - } - } else { - if ($studentDegreeChoicePosition >= 6) { - return '#FE2E2E'; - } - if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { - return '#F6CECE'; - } - if ($studentDegreeChoicePosition == 3) { - return '#FFFFFF'; - } - } - } - - /** - * Return the color code for student answer. - * - * @param $studentAnwser - * @param $expectedAnswer - * @param $studentDegreeChoicePosition - * - * @return int - */ - public function getStatusResponse($studentAnwser, $expectedAnswer, $studentDegreeChoicePosition) - { - $checkResult = ($studentAnwser == $expectedAnswer) ? true : false; - if ($checkResult) { - if ($studentDegreeChoicePosition >= 6) { - return self::LEVEL_DARKGREEN; - } - if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { - return self::LEVEL_LIGHTGREEN; - } - if ($studentDegreeChoicePosition == 3) { - return self::LEVEL_WHITE; - } - } else { - if ($studentDegreeChoicePosition >= 6) { - return self::LEVEL_DARKRED; - } - if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { - return self::LEVEL_LIGHTRED; - } - if ($studentDegreeChoicePosition == 3) { - return self::LEVEL_WHITE; - } - } - } - - /** - * Method to recover labels for color codes. - * - * @param $studentAnswer - * @param $expectedAnswer - * @param $studentDegreeChoicePosition - * - * @return string - */ - public function getCodeResponse($studentAnswer, $expectedAnswer, $studentDegreeChoicePosition) - { - $checkResult = ($studentAnswer == $expectedAnswer) ? true : false; - if ($checkResult) { - if ($studentDegreeChoicePosition >= 6) { - return get_lang('DegreeOfCertaintyVerySure'); - } - if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { - return get_lang('DegreeOfCertaintyPrettySure'); - } - if ($studentDegreeChoicePosition == 3) { - return get_lang('DegreeOfCertaintyDeclaredIgnorance'); - } - } else { - if ($studentDegreeChoicePosition >= 6) { - return get_lang('DegreeOfCertaintyVeryUnsure'); - } - if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { - return get_lang('DegreeOfCertaintyUnsure'); - } - if ($studentDegreeChoicePosition == 3) { - return get_lang('DegreeOfCertaintyIgnorance'); - } - } - } - - /** - * Method to show the code color and his meaning for the test result. - */ - public static function showColorCode() - { +type = MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY; + $this->isContent = $this->getIsContent(); + $this->optionsTitle = [1 => 'Answers', 2 => 'DegreeOfCertaintyThatMyAnswerIsCorrect']; + $this->options = [ + 1 => 'True', + 2 => 'False', + 3 => '50%', + 4 => '60%', + 5 => '70%', + 6 => '80%', + 7 => '90%', + 8 => '100%', + ]; + } + + /** + * Redefines Question::createAnswersForm: creates the HTML form to answer the question. + * + * @uses \globals $text and $class, defined in the calling script + * + * @param FormValidator $form + * + * @throws Exception + * @throws HTML_QuickForm_Error + */ + public function createAnswersForm($form) + { + global $text, $class; + $nbAnswers = isset($_POST['nb_answers']) ? (int) $_POST['nb_answers'] : 4; + // The previous default value was 2. See task #1759. + $nbAnswers += (isset($_POST['lessAnswers']) ? -1 : (isset($_POST['moreAnswers']) ? 1 : 0)); + + $courseId = api_get_course_int_id(); + $objEx = $_SESSION['objExercise']; + $renderer = &$form->defaultRenderer(); + $defaults = []; + + $html = '
' - .get_lang("Choice") - .'' - .get_lang("ExpectedChoice") - .'' - .get_lang("Answer") - .'' - .get_lang("YourDegreeOfCertainty") - .' '.get_lang("Comment").' 
'; + + // show column comment when feedback is enable + if ($objEx->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) { + $html .= ''; + } + $html .= ''; + $form->addElement('label', get_lang('Answers').'
', $html); + + $correct = 0; + $answer = null; + if (!empty($this->id)) { + $answer = new Answer($this->id); + $answer->read(); + if (count($answer->nbrAnswers) > 0 && !$form->isSubmitted()) { + $nbAnswers = $answer->nbrAnswers; + } + } + + $form->addElement('hidden', 'nb_answers'); + $boxesNames = []; + + if ($nbAnswers < 1) { + $nbAnswers = 1; + echo Display::return_message(get_lang('YouHaveToCreateAtLeastOneAnswer')); + } + + // Can be more options + $optionData = Question::readQuestionOption($this->id, $courseId); + + for ($i = 1; $i <= $nbAnswers; ++$i) { + $renderer->setElementTemplate( + '', + 'correct['.$i.']' + ); + $renderer->setElementTemplate( + '', + 'counter['.$i.']' + ); + $renderer->setElementTemplate( + '', + 'answer['.$i.']' + ); + $renderer->setElementTemplate( + '', + 'comment['.$i.']' + ); + + $answerNumber = $form->addElement('text', 'counter['.$i.']', null, 'value="'.$i.'"'); + $answerNumber->freeze(); + + if (is_object($answer)) { + $defaults['answer['.$i.']'] = $answer->answer[$i]; + $defaults['comment['.$i.']'] = $answer->comment[$i]; + $defaults['weighting['.$i.']'] = float_format($answer->weighting[$i], 1); + + $correct = $answer->correct[$i]; + $defaults['correct['.$i.']'] = $correct; + + $j = 1; + if (!empty($optionData)) { + foreach ($optionData as $id => $data) { + $form->addElement('radio', 'correct['.$i.']', null, null, $id); + $j++; + if ($j == 3) { + break; + } + } + } + } else { + $form->addElement('radio', 'correct['.$i.']', null, null, 1); + $form->addElement('radio', 'correct['.$i.']', null, null, 2); + + $defaults['answer['.$i.']'] = ''; + $defaults['comment['.$i.']'] = ''; + $defaults['correct['.$i.']'] = ''; + } + + $boxesNames[] = 'correct['.$i.']'; + $form->addElement( + 'html_editor', + 'answer['.$i.']', + null, + ['style' => 'vertical-align:middle;'], + ['ToolbarSet' => 'TestProposedAnswer', 'Width' => '100%', 'Height' => '100']); + $form->addRule('answer['.$i.']', get_lang('ThisFieldIsRequired'), 'required'); + + // show comment when feedback is enable + if ($objEx->selectFeedbackType() != EXERCISE_FEEDBACK_TYPE_EXAM) { + $form->addElement('html_editor', + 'comment['.$i.']', + null, + ['style' => 'vertical-align:middle;'], + ['ToolbarSet' => 'TestProposedAnswer', 'Width' => '100%', 'Height' => '100']); + } + $form->addElement('html', ''); + } + + $form->addElement('html', '
' + .get_lang('Number') + .'' + .get_lang('True') + .'' + .get_lang('False') + .'' + .get_lang('Answer') + .''.get_lang('Comment').'
{error}
{element}
{error}
{element}
{error}
{element}
{error}
{element}
'); + $form->addElement('html', '
'); + + // 3 scores + $form->addElement('text', 'option[1]', get_lang('Correct'), ['class' => 'span1', 'value' => '1']); + $form->addElement('text', 'option[2]', get_lang('Wrong'), ['class' => 'span1', 'value' => '-0.5']); + + $form->addElement('hidden', 'option[3]', 0); + + $form->addRule('option[1]', get_lang('ThisFieldIsRequired'), 'required'); + $form->addRule('option[2]', get_lang('ThisFieldIsRequired'), 'required'); + + $form->addElement('html', ''); + $form->addElement('hidden', 'options_count', 3); + $form->addElement('html', '


'); + + //Extra values True, false, Dont known + if (!empty($this->extra)) { + $scores = explode(':', $this->extra); + if (!empty($scores)) { + for ($i = 1; $i <= 3; $i++) { + $defaults['option['.$i.']'] = $scores[$i - 1]; + } + } + } + + if ($objEx->edit_exercise_in_lp == true) { + $form->addElement('submit', 'lessAnswers', get_lang('LessAnswer'), 'class="btn minus"'); + $form->addElement('submit', 'moreAnswers', get_lang('PlusAnswer'), 'class="btn plus"'); + //$text and $class defined in calling script + $form->addElement('submit', 'submitQuestion', $text, 'class="'.$class.'"'); + } + $renderer->setElementTemplate('{element} ', 'lessAnswers'); + $renderer->setElementTemplate('{element} ', 'submitQuestion'); + $renderer->setElementTemplate('{element} ', 'moreAnswers'); + $form->addElement('html', ''); + $defaults['correct'] = $correct; + + if (!empty($this->id)) { + $form->setDefaults($defaults); + } else { + //if ($this -> isContent == 1) { + $form->setDefaults($defaults); + //} + } + $form->setConstants(['nb_answers' => $nbAnswers]); + } + + /** + * abstract function which creates the form to create / edit the answers of the question. + * + * @param FormValidator $form + * @param Exercise $exercise + */ + public function processAnswersCreation($form, $exercise) + { + $questionWeighting = 0; + $objAnswer = new Answer($this->id); + $nbAnswers = $form->getSubmitValue('nb_answers'); + + $courseId = api_get_course_int_id(); + + $correct = []; + $options = Question::readQuestionOption($this->id, $courseId); + + if (!empty($options)) { + foreach ($options as $optionData) { + $id = $optionData['id']; + unset($optionData['id']); + Question::updateQuestionOption($id, $optionData, $courseId); + } + } else { + for ($i = 1; $i <= 8; $i++) { + $lastId = Question::saveQuestionOption($this->id, $this->options[$i], $courseId, $i); + $correct[$i] = $lastId; + } + } + + /* Getting quiz_question_options (true, false, doubt) because + it's possible that there are more options in the future */ + + $newOptions = Question::readQuestionOption($this->id, $courseId); + + $sortedByPosition = []; + foreach ($newOptions as $item) { + $sortedByPosition[$item['position']] = $item; + } + + /* Saving quiz_question.extra values that has the correct scores of + the true, false, doubt options registered in this format + XX:YY:ZZZ where XX is a float score value. */ + $extraValues = []; + + for ($i = 1; $i <= 3; $i++) { + $score = trim($form->getSubmitValue('option['.$i.']')); + $extraValues[] = $score; + } + $this->setExtra(implode(':', $extraValues)); + + for ($i = 1; $i <= $nbAnswers; $i++) { + $answer = trim($form->getSubmitValue('answer['.$i.']')); + $comment = trim($form->getSubmitValue('comment['.$i.']')); + $goodAnswer = trim($form->getSubmitValue('correct['.$i.']')); + if (empty($options)) { + // If this is the first time that the question is created then change + // the default values from the form 1 and 2 by the correct "option id" registered + $goodAnswer = $sortedByPosition[$goodAnswer]['id']; + } + $questionWeighting += $extraValues[0]; //By default 0 has the correct answers + $objAnswer->createAnswer($answer, $goodAnswer, $comment, '', $i); + } + + // saves the answers into the data base + $objAnswer->save(); + + // sets the total weighting of the question + $this->updateWeighting($questionWeighting); + $this->save($exercise); + } + + /** + * Show result table headers. + * + * @param int $feedbackType + * @param int $counter + * @param float $score + * + * @return null|string + */ + public function return_header($feedbackType = null, $counter = null, $score = null) + { + $header = parent::return_header($feedbackType, $counter, $score); + $header .= '' + ; + if ($feedbackType != EXERCISE_FEEDBACK_TYPE_EXAM) { + $header .= ''; + } else { + $header .= ''; + } + $header .= ''; + + return $header; + } + + /** + * Method to recovery color to show by precision of the student's answer. + * + * @param $studentAnwser + * @param $expectedAnswer + * @param $studentDegreeChoicePosition + * + * @return string + */ + public function getColorResponse($studentAnwser, $expectedAnswer, $studentDegreeChoicePosition) + { + $checkResult = ($studentAnwser == $expectedAnswer) ? true : false; + if ($checkResult) { + if ($studentDegreeChoicePosition >= 6) { + return '#088A08'; + } + if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { + return '#A9F5A9'; + } + if ($studentDegreeChoicePosition == 3) { + return '#FFFFFF'; + } + } else { + if ($studentDegreeChoicePosition >= 6) { + return '#FE2E2E'; + } + if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { + return '#F6CECE'; + } + if ($studentDegreeChoicePosition == 3) { + return '#FFFFFF'; + } + } + } + + /** + * Return the color code for student answer. + * + * @param $studentAnwser + * @param $expectedAnswer + * @param $studentDegreeChoicePosition + * + * @return int + */ + public function getStatusResponse($studentAnwser, $expectedAnswer, $studentDegreeChoicePosition) + { + $checkResult = ($studentAnwser == $expectedAnswer) ? true : false; + if ($checkResult) { + if ($studentDegreeChoicePosition >= 6) { + return self::LEVEL_DARKGREEN; + } + if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { + return self::LEVEL_LIGHTGREEN; + } + if ($studentDegreeChoicePosition == 3) { + return self::LEVEL_WHITE; + } + } else { + if ($studentDegreeChoicePosition >= 6) { + return self::LEVEL_DARKRED; + } + if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { + return self::LEVEL_LIGHTRED; + } + if ($studentDegreeChoicePosition == 3) { + return self::LEVEL_WHITE; + } + } + } + + /** + * Method to recover labels for color codes. + * + * @param $studentAnswer + * @param $expectedAnswer + * @param $studentDegreeChoicePosition + * + * @return string + */ + public function getCodeResponse($studentAnswer, $expectedAnswer, $studentDegreeChoicePosition) + { + $checkResult = ($studentAnswer == $expectedAnswer) ? true : false; + if ($checkResult) { + if ($studentDegreeChoicePosition >= 6) { + return get_lang('DegreeOfCertaintyVerySure'); + } + if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { + return get_lang('DegreeOfCertaintyPrettySure'); + } + if ($studentDegreeChoicePosition == 3) { + return get_lang('DegreeOfCertaintyDeclaredIgnorance'); + } + } else { + if ($studentDegreeChoicePosition >= 6) { + return get_lang('DegreeOfCertaintyVeryUnsure'); + } + if ($studentDegreeChoicePosition >= 4 && $studentDegreeChoicePosition <= 5) { + return get_lang('DegreeOfCertaintyUnsure'); + } + if ($studentDegreeChoicePosition == 3) { + return get_lang('DegreeOfCertaintyIgnorance'); + } + } + } + + /** + * Method to show the code color and his meaning for the test result. + */ + public static function showColorCode() + { ?>
' + .get_lang("Choice") + .'' + .get_lang("ExpectedChoice") + .'' + .get_lang("Answer") + .'' + .get_lang("YourDegreeOfCertainty") + .' '.get_lang("Comment").' 
@@ -481,173 +485,175 @@ class MultipleAnswerTrueFalseDegreeCertainty extends Question

- gather_questions_categories == 1) { // original - $groupCategoriesByBracket = true; - } else { - $groupCategoriesByBracket = false; - } - - if ($groupCategoriesByBracket) { - $scoreList = []; - $categoryPrefixList = []; // categoryPrefix['Math'] = firstCategoryId for this prefix - // rebuild $scoreList factorizing data with category prefix - foreach ($scoreListAll as $categoryId => $scoreListForCategory) { - $objCategory = new Testcategory(); - $objCategoryNum = $objCategory->getCategory($categoryId); - preg_match("/^\[([^]]+)\]/", $objCategoryNum->name, $matches); - - if (count($matches) > 1) { - // check if we have already see this prefix - if (array_key_exists($matches[1], $categoryPrefixList)) { - // add the result color for this entry - $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_DARKGREEN] += - $scoreListForCategory[self::LEVEL_DARKGREEN]; - $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_LIGHTGREEN] += - $scoreListForCategory[self::LEVEL_LIGHTGREEN]; - $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_WHITE] += - $scoreListForCategory[self::LEVEL_WHITE]; - $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_LIGHTRED] += - $scoreListForCategory[self::LEVEL_LIGHTRED]; - $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_DARKRED] += - $scoreListForCategory[self::LEVEL_DARKRED]; - } else { - $categoryPrefixList[$matches[1]] = $categoryId; - $scoreList[$categoryId] = $scoreListAll[$categoryId]; - } - } else { - // doesn't match the prefix '[math] Math category' - $scoreList[$categoryId] = $scoreListAll[$categoryId]; - } - } - } else { - $scoreList = $scoreListAll; - } - - // get the max height of item to have each table the same height if displayed side by side - foreach ($scoreList as $categoryId => $scoreListForCategory) { - $testCategory = new TestCategory(); - $categoryQuestionName = $testCategory->getCategory($categoryId)->name; - list($null, $height) = self::displayDegreeChart( - $scoreListForCategory, - 300, - '', - 1, - 0, - false, - true, - groupCategoriesByBracket - ); - if ($height > $maxHeight) { - $maxHeight = $height; - } - } - - if (count($scoreList) > 1) { - $boxWidth = $sizeRatio * 300 * 2 + 54; - } else { - $boxWidth = $sizeRatio * 300 + 54; - } - - $html = '
'; - $html .= '

'.$title.'

'; - - // get the html of items - $i = 0; - foreach ($scoreList as $categoryId => $scoreListForCategory) { - $oCategory = new Testcategory(); - $categoryQuestionName = $oCategory->getCategory($categoryId)->name; - - if ($categoryQuestionName == '') { - $categoryName = get_lang('WithoutCategory'); - } else { - $categoryName = $oCategory->name; - } - - $html .= '
'; - $html .= self::displayDegreeChart( - $scoreListForCategory, - 300, - $categoryName, - 1, - $maxHeight, - false, - false, - $groupCategoriesByBracket - ); - $html .= '
'; - - if ($i == 1) { - $html .= '
 
'; - $i = 0; - } else { - $i++; - } - } - - return $html.'
 
'; - } - - /** - * Return HTML code for the $scoreList of MultipleAnswerTrueFalseDegreeCertainty questions. - * - * @param $scoreList - * @param int $sizeRatio - * - * @return string - */ - public static function displayDegreeChart( - $scoreList, - $widthTable, - $title = '', - $sizeRatio = 1, - $minHeight = 0, - $displayExplanationText = true, - $returnHeight = false, - $groupCategoriesByBracket = false, - $numberOfQuestions = 0 - ) { - $topAndBottomMargin = 10; - - $colorList = [self::LEVEL_DARKRED, - self::LEVEL_LIGHTRED, - self::LEVEL_WHITE, - self::LEVEL_LIGHTGREEN, - self::LEVEL_DARKGREEN, - ]; - - // get total attempt number - $highterColorHeight = 0; - - foreach ($scoreList as $color => $number) { - if ($number > $highterColorHeight) { - $highterColorHeight = $number; - } - } - - $totalAttemptNumber = $numberOfQuestions; - - $verticalLineHeight = $highterColorHeight * $sizeRatio * 2 + 122 + $topAndBottomMargin * 2; - if ($verticalLineHeight < $minHeight) { - $minHeightCorrection = $minHeight - $verticalLineHeight; - $verticalLineHeight += $minHeightCorrection; - } - - // draw chart + gather_questions_categories == 1) { // original + $groupCategoriesByBracket = true; + } else { + $groupCategoriesByBracket = false; + } + + if ($groupCategoriesByBracket) { + $scoreList = []; + $categoryPrefixList = []; // categoryPrefix['Math'] = firstCategoryId for this prefix + // rebuild $scoreList factorizing data with category prefix + foreach ($scoreListAll as $categoryId => $scoreListForCategory) { + $objCategory = new Testcategory(); + $objCategoryNum = $objCategory->getCategory($categoryId); + preg_match("/^\[([^]]+)\]/", $objCategoryNum->name, $matches); + + if (count($matches) > 1) { + // check if we have already see this prefix + if (array_key_exists($matches[1], $categoryPrefixList)) { + // add the result color for this entry + $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_DARKGREEN] += + $scoreListForCategory[self::LEVEL_DARKGREEN]; + $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_LIGHTGREEN] += + $scoreListForCategory[self::LEVEL_LIGHTGREEN]; + $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_WHITE] += + $scoreListForCategory[self::LEVEL_WHITE]; + $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_LIGHTRED] += + $scoreListForCategory[self::LEVEL_LIGHTRED]; + $scoreList[$categoryPrefixList[$matches[1]]][self::LEVEL_DARKRED] += + $scoreListForCategory[self::LEVEL_DARKRED]; + } else { + $categoryPrefixList[$matches[1]] = $categoryId; + $scoreList[$categoryId] = $scoreListAll[$categoryId]; + } + } else { + // doesn't match the prefix '[math] Math category' + $scoreList[$categoryId] = $scoreListAll[$categoryId]; + } + } + } else { + $scoreList = $scoreListAll; + } + + // get the max height of item to have each table the same height if displayed side by side + foreach ($scoreList as $categoryId => $scoreListForCategory) { + $testCategory = new TestCategory(); + $categoryQuestionName = $testCategory->getCategory($categoryId)->name; + list($null, $height) = self::displayDegreeChart( + $scoreListForCategory, + 300, + '', + 1, + 0, + false, + true, + groupCategoriesByBracket + ); + if ($height > $maxHeight) { + $maxHeight = $height; + } + } + + if (count($scoreList) > 1) { + $boxWidth = $sizeRatio * 300 * 2 + 54; + } else { + $boxWidth = $sizeRatio * 300 + 54; + } + + $html = '
'; + $html .= '

'.$title.'

'; + + // get the html of items + $i = 0; + foreach ($scoreList as $categoryId => $scoreListForCategory) { + $oCategory = new Testcategory(); + $categoryQuestionName = $oCategory->getCategory($categoryId)->name; + + if ($categoryQuestionName == '') { + $categoryName = get_lang('WithoutCategory'); + } else { + $categoryName = $oCategory->name; + } + + $html .= '
'; + $html .= self::displayDegreeChart( + $scoreListForCategory, + 300, + $categoryName, + 1, + $maxHeight, + false, + false, + $groupCategoriesByBracket + ); + $html .= '
'; + + if ($i == 1) { + $html .= '
 
'; + $i = 0; + } else { + $i++; + } + } + + return $html.'
 
'; + } + + /** + * Return HTML code for the $scoreList of MultipleAnswerTrueFalseDegreeCertainty questions. + * + * @param $scoreList + * @param int $sizeRatio + * + * @return string + */ + public static function displayDegreeChart( + $scoreList, + $widthTable, + $title = '', + $sizeRatio = 1, + $minHeight = 0, + $displayExplanationText = true, + $returnHeight = false, + $groupCategoriesByBracket = false, + $numberOfQuestions = 0 + ) { + $topAndBottomMargin = 10; + + $colorList = [self::LEVEL_DARKRED, + self::LEVEL_LIGHTRED, + self::LEVEL_WHITE, + self::LEVEL_LIGHTGREEN, + self::LEVEL_DARKGREEN, + ]; + + // get total attempt number + $highterColorHeight = 0; + + foreach ($scoreList as $color => $number) { + if ($number > $highterColorHeight) { + $highterColorHeight = $number; + } + } + + $totalAttemptNumber = $numberOfQuestions; + + $verticalLineHeight = $highterColorHeight * $sizeRatio * 2 + 122 + $topAndBottomMargin * 2; + if ($verticalLineHeight < $minHeight) { + $minHeightCorrection = $minHeight - $verticalLineHeight; + $verticalLineHeight += $minHeightCorrection; + } + + // draw chart $html = ''; - - if ($groupCategoriesByBracket) { - $title = api_preg_replace("/[^]]*$/", "", $title); - $title = ucfirst(api_preg_replace("/[\[\]]/", "", $title)); - } - - $display = (strpos($title, "ensemble") > 0) ? - $title."
($totalAttemptNumber questions)" : - $title; - $textSize = ( - strpos($title, "ensemble") > 0 || - strpos($title, "votre dernier résultat à ce test") > 0 - ) ? 100 : 80; - - if ($displayExplanationText) { - // global chart - $classGlobalChart = "globalChart"; - } else { - $classGlobalChart = ""; - } - - $html .= '' - ; - $html .= '' - ; - - $nbResponsesInc = (isset($scoreList[4]) || isset($scoreList[5])) ? $scoreList[4] + $scoreList[5] : 0; - $nbResponsesIng = (isset($scoreList[3])) ? $scoreList[3] : 0; - $nbResponsesCor = (isset($scoreList[1]) || isset($scoreList[2])) ? $scoreList[1] + $scoreList[2] : 0; - - $colWidth = $widthTable / 5; - + '; + + if ($groupCategoriesByBracket) { + $title = api_preg_replace("/[^]]*$/", "", $title); + $title = ucfirst(api_preg_replace("/[\[\]]/", "", $title)); + } + + $display = (strpos($title, "ensemble") > 0) ? + $title."
($totalAttemptNumber questions)" : + $title; + $textSize = ( + strpos($title, "ensemble") > 0 || + strpos($title, "votre dernier résultat à ce test") > 0 + ) ? 100 : 80; + + if ($displayExplanationText) { + // global chart + $classGlobalChart = "globalChart"; + } else { + $classGlobalChart = ""; + } + + $html .= '
' - .$display - .'
' + ; + $html .= '' + ; + + $nbResponsesInc = (isset($scoreList[4]) || isset($scoreList[5])) ? $scoreList[4] + $scoreList[5] : 0; + $nbResponsesIng = (isset($scoreList[3])) ? $scoreList[3] : 0; + $nbResponsesCor = (isset($scoreList[1]) || isset($scoreList[2])) ? $scoreList[1] + $scoreList[2] : 0; + + $colWidth = $widthTable / 5; + $html .= ' - '; - $html .= ''; - - foreach ($colorList as $i => $color) { - if (array_key_exists($color, $scoreList)) { - $scoreOnBottom = $scoreList[$color]; // height of the colored area on the bottom - } else { - $scoreOnBottom = 0; - } - - $sizeOnBottom = $scoreOnBottom * $sizeRatio * 2; - - if ($i == 1 || $i == 2) { - $html .= ''; - } - - $html .= ''; - - if ($displayExplanationText) { - // Display of histogram text - $explainHistoList = [ - 'DegreeOfCertaintyVeryUnsure', - 'DegreeOfCertaintyUnsure', - 'DegreeOfCertaintyIgnorance', - 'DegreeOfCertaintyPrettySure', - 'DegreeOfCertaintyVerySure', ]; - $html .= ''; - $i = 0; - foreach ($explainHistoList as $explain) { - if ($i == 1 || $i == 2) { - $class = "borderRight"; - } else { - $class = ""; - } - $html .= ''; - $i++; - } - $html .= ''; - } - - $html .= '
' + .$display + .'
'. + style="width:'.($colWidth * 2).'px; font-size:'.$textSize.'%;">'. sprintf(get_lang('IncorrectAnswersX'), $nbResponsesInc).' '. + style="width:'.$colWidth.'px; font-size :'.$textSize.'%;">'. sprintf(get_lang('IgnoranceAnswersX'), $nbResponsesIng).' '. + style="width:'.($colWidth * 2).'px; font-size:'.$textSize.'%;">'. sprintf(get_lang('CorrectAnswersX'), $nbResponsesCor).'
' - ; - } else { - $html .= '' - ; - } - $html .= '
' - .$scoreOnBottom - .'
 
' - ; - $html .= '
' - ; - $html .= get_lang($explain); - $html .= '
'; - - if ($returnHeight) { - return [$html, $verticalLineHeight]; - } else { - return $html; - } - } - - /** - * return previous attempt id for this test for student, 0 if no previous attempt. - * - * @param $exeId - * - * @return int - */ - public static function getPreviousAttemptId($exeId) - { - $tblTrackEExercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); + '; + $html .= ''; + + foreach ($colorList as $i => $color) { + if (array_key_exists($color, $scoreList)) { + $scoreOnBottom = $scoreList[$color]; // height of the colored area on the bottom + } else { + $scoreOnBottom = 0; + } + + $sizeOnBottom = $scoreOnBottom * $sizeRatio * 2; + + if ($i == 1 || $i == 2) { + $html .= '' + ; + } else { + $html .= '' + ; + } + $html .= '
' + .$scoreOnBottom + .'
 
' + ; + $html .= ''; + } + + $html .= ''; + + if ($displayExplanationText) { + // Display of histogram text + $explainHistoList = [ + 'DegreeOfCertaintyVeryUnsure', + 'DegreeOfCertaintyUnsure', + 'DegreeOfCertaintyIgnorance', + 'DegreeOfCertaintyPrettySure', + 'DegreeOfCertaintyVerySure', ]; + $html .= ''; + $i = 0; + foreach ($explainHistoList as $explain) { + if ($i == 1 || $i == 2) { + $class = "borderRight"; + } else { + $class = ""; + } + $html .= '' + ; + $html .= get_lang($explain); + $html .= ''; + $i++; + } + $html .= ''; + } + + $html .= ''; + + if ($returnHeight) { + return [$html, $verticalLineHeight]; + } else { + return $html; + } + } + + /** + * return previous attempt id for this test for student, 0 if no previous attempt. + * + * @param $exeId + * + * @return int + */ + public static function getPreviousAttemptId($exeId) + { + $tblTrackEExercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); $sql = "SELECT * FROM $tblTrackEExercise - WHERE exe_id = ".intval($exeId); - $res = Database::query($sql); - - if (Database::num_rows($res) == 0) { - // if we cannot find the exe_id - return 0; - } - - $data = Database::fetch_assoc($res); - $courseCode = $data['c_id']; - $exerciseId = $data['exe_exo_id']; - $userId = $data['exe_user_id']; - $attemptDate = $data['exe_date']; - - if ($attemptDate == "0000-00-00 00:00:00") { - // incomplete attempt, close it before continue - return 0; - } - - // look for previous attempt - $exerciseId = (int) $exerciseId; - $userId = (int) $userId; + WHERE exe_id = ".intval($exeId); + $res = Database::query($sql); + + if (Database::num_rows($res) == 0) { + // if we cannot find the exe_id + return 0; + } + + $data = Database::fetch_assoc($res); + $courseCode = $data['c_id']; + $exerciseId = $data['exe_exo_id']; + $userId = $data['exe_user_id']; + $attemptDate = $data['exe_date']; + + if ($attemptDate == "0000-00-00 00:00:00") { + // incomplete attempt, close it before continue + return 0; + } + + // look for previous attempt + $exerciseId = (int) $exerciseId; + $userId = (int) $userId; $sql = "SELECT * FROM $tblTrackEExercise WHERE c_id = '$courseCode' @@ -918,374 +924,373 @@ class MultipleAnswerTrueFalseDegreeCertainty extends Question AND status = '' AND exe_date > '0000-00-00 00:00:00' AND exe_date < '$attemptDate' - ORDER BY exe_date DESC"; - - $res = Database::query($sql); - - if (Database::num_rows($res) == 0) { - // no previous attempt - return 0; - } - - $data = Database::fetch_assoc($res); - - return $data['exe_id']; - } - - /** - * return an array of number of answer color for exe attempt - * for question type = MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY - * e.g. - * [LEVEL_DARKGREEN => 3, LEVEL_LIGHTGREEN => 0, LEVEL_WHITE => 5, LEVEL_LIGHTRED => 12, LEVEL_DARKTRED => 0]. - * - * @param $exeId - * - * @return array - */ - public static function getColorNumberListForAttempt($exeId) - { - $result = [self::LEVEL_DARKGREEN => 0, - self::LEVEL_LIGHTGREEN => 0, - self::LEVEL_WHITE => 0, - self::LEVEL_LIGHTRED => 0, - self::LEVEL_DARKRED => 0, - ]; - - $attemptInfoList = self::getExerciseAttemptInfo($exeId); - - foreach ($attemptInfoList as $attemptInfo) { - $oQuestion = new MultipleAnswerTrueFalseDegreeCertainty(); - $oQuestion->read($attemptInfo['question_id']); - if ($oQuestion->type == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) { - $answerColor = self::getAnswerColor($exeId, $attemptInfo['question_id'], $attemptInfo['position']); - if ($answerColor) { - $result[$answerColor]++; - } - } - } - - return $result; - } - - /** - * return an array of number of color for question type = MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY - * for each question category. - * - * e.g. - * [ - * (categoryId=)5 => [LEVEL_DARKGREEN => 3, LEVEL_WHITE => 5, LEVEL_LIGHTRED => 12] - * (categoryId=)2 => [LEVEL_DARKGREEN => 8, LEVEL_LIGHTRED => 2, LEVEL_DARKTRED => 8] - * (categoryId=)0 => [LEVEL_DARKGREEN => 1, - * LEVEL_LIGHTGREEN => 2, - * LEVEL_WHITE => 6, - * LEVEL_LIGHTRED => 1, - * LEVEL_DARKTRED => 9] - * ] - * - * @param $exeId - * - * @return array - */ - public static function getColorNumberListForAttemptByCategory($exeId) - { - $result = []; - $attemptInfoList = self::getExerciseAttemptInfo($exeId); - - foreach ($attemptInfoList as $i => $attemptInfo) { - $oQuestion = new MultipleAnswerTrueFalseDegreeCertainty(); - $oQuestion->read($attemptInfo['question_id']); - if ($oQuestion->type == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) { - $questionCategory = Testcategory::getCategoryForQuestion($attemptInfo['question_id']); - - if (!array_key_exists($questionCategory, $result)) { - $result[$questionCategory] = []; - } - - $answerColor = self::getAnswerColor($exeId, $attemptInfo['question_id'], $attemptInfo['position']); - if ($answerColor) { - $result[$questionCategory][$answerColor]++; - } - } - } - - return $result; - } - - /** - * Return true if answer of $exeId, $questionId, $position is correct, otherwise return false. - * - * @param $exeId - * @param $questionId - * @param $position - * - * @return bool - */ - public static function getAnswerColor($exeId, $questionId, $position) - { - $attemptInfoList = self::getExerciseAttemptInfo($exeId, $questionId, $position); - - if (count($attemptInfoList) != 1) { - // havent got the answer - return 0; - } - - $answerCodes = $attemptInfoList[0]['answer']; - - // student answer - $splitAnswer = preg_split("/:/", $answerCodes); - // get correct answer option id - $correctAnswerOptionId = self::getCorrectAnswerOptionId($splitAnswer[0]); - if ($correctAnswerOptionId == 0) { - // error returning the correct answer option id - return 0; - } - - // get student answer option id - $studentAnswerOptionId = $splitAnswer[1]; - - // we got the correct answer option id, let's compare ti with the student answer - $percentage = self::getPercentagePosition($splitAnswer[2]); - if ($studentAnswerOptionId == $correctAnswerOptionId) { - // yeah, student got correct answer - switch ($percentage) { - case 3: - return self::LEVEL_WHITE; - case 4: - case 5: - return self::LEVEL_LIGHTGREEN; - case 6: - case 7: - case 8: - return self::LEVEL_DARKGREEN; - default: - return 0; - } - } else { - // bummer, wrong answer dude - switch ($percentage) { - case 3: - return self::LEVEL_WHITE; - case 4: - case 5: - return self::LEVEL_LIGHTRED; - case 6: - case 7: - case 8: - return self::LEVEL_DARKRED; - default: - return 0; - } - } - } - - /** - * Return the position of certitude %age choose by student. - * - * @param $optionId - * - * @return int - */ - public static function getPercentagePosition($optionId) - { - $tblAnswerOption = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); - $courseId = api_get_course_int_id(); + ORDER BY exe_date DESC"; + + $res = Database::query($sql); + + if (Database::num_rows($res) == 0) { + // no previous attempt + return 0; + } + + $data = Database::fetch_assoc($res); + + return $data['exe_id']; + } + + /** + * return an array of number of answer color for exe attempt + * for question type = MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY + * e.g. + * [LEVEL_DARKGREEN => 3, LEVEL_LIGHTGREEN => 0, LEVEL_WHITE => 5, LEVEL_LIGHTRED => 12, LEVEL_DARKTRED => 0]. + * + * @param $exeId + * + * @return array + */ + public static function getColorNumberListForAttempt($exeId) + { + $result = [self::LEVEL_DARKGREEN => 0, + self::LEVEL_LIGHTGREEN => 0, + self::LEVEL_WHITE => 0, + self::LEVEL_LIGHTRED => 0, + self::LEVEL_DARKRED => 0, + ]; + + $attemptInfoList = self::getExerciseAttemptInfo($exeId); + + foreach ($attemptInfoList as $attemptInfo) { + $oQuestion = new MultipleAnswerTrueFalseDegreeCertainty(); + $oQuestion->read($attemptInfo['question_id']); + if ($oQuestion->type == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) { + $answerColor = self::getAnswerColor($exeId, $attemptInfo['question_id'], $attemptInfo['position']); + if ($answerColor) { + $result[$answerColor]++; + } + } + } + + return $result; + } + + /** + * return an array of number of color for question type = MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY + * for each question category. + * + * e.g. + * [ + * (categoryId=)5 => [LEVEL_DARKGREEN => 3, LEVEL_WHITE => 5, LEVEL_LIGHTRED => 12] + * (categoryId=)2 => [LEVEL_DARKGREEN => 8, LEVEL_LIGHTRED => 2, LEVEL_DARKTRED => 8] + * (categoryId=)0 => [LEVEL_DARKGREEN => 1, + * LEVEL_LIGHTGREEN => 2, + * LEVEL_WHITE => 6, + * LEVEL_LIGHTRED => 1, + * LEVEL_DARKTRED => 9] + * ] + * + * @param $exeId + * + * @return array + */ + public static function getColorNumberListForAttemptByCategory($exeId) + { + $result = []; + $attemptInfoList = self::getExerciseAttemptInfo($exeId); + + foreach ($attemptInfoList as $i => $attemptInfo) { + $oQuestion = new MultipleAnswerTrueFalseDegreeCertainty(); + $oQuestion->read($attemptInfo['question_id']); + if ($oQuestion->type == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) { + $questionCategory = Testcategory::getCategoryForQuestion($attemptInfo['question_id']); + + if (!array_key_exists($questionCategory, $result)) { + $result[$questionCategory] = []; + } + + $answerColor = self::getAnswerColor($exeId, $attemptInfo['question_id'], $attemptInfo['position']); + if ($answerColor) { + $result[$questionCategory][$answerColor]++; + } + } + } + + return $result; + } + + /** + * Return true if answer of $exeId, $questionId, $position is correct, otherwise return false. + * + * @param $exeId + * @param $questionId + * @param $position + * + * @return bool + */ + public static function getAnswerColor($exeId, $questionId, $position) + { + $attemptInfoList = self::getExerciseAttemptInfo($exeId, $questionId, $position); + + if (count($attemptInfoList) != 1) { + // havent got the answer + return 0; + } + + $answerCodes = $attemptInfoList[0]['answer']; + + // student answer + $splitAnswer = preg_split("/:/", $answerCodes); + // get correct answer option id + $correctAnswerOptionId = self::getCorrectAnswerOptionId($splitAnswer[0]); + if ($correctAnswerOptionId == 0) { + // error returning the correct answer option id + return 0; + } + + // get student answer option id + $studentAnswerOptionId = $splitAnswer[1]; + + // we got the correct answer option id, let's compare ti with the student answer + $percentage = self::getPercentagePosition($splitAnswer[2]); + if ($studentAnswerOptionId == $correctAnswerOptionId) { + // yeah, student got correct answer + switch ($percentage) { + case 3: + return self::LEVEL_WHITE; + case 4: + case 5: + return self::LEVEL_LIGHTGREEN; + case 6: + case 7: + case 8: + return self::LEVEL_DARKGREEN; + default: + return 0; + } + } else { + // bummer, wrong answer dude + switch ($percentage) { + case 3: + return self::LEVEL_WHITE; + case 4: + case 5: + return self::LEVEL_LIGHTRED; + case 6: + case 7: + case 8: + return self::LEVEL_DARKRED; + default: + return 0; + } + } + } + + /** + * Return the position of certitude %age choose by student. + * + * @param $optionId + * + * @return int + */ + public static function getPercentagePosition($optionId) + { + $tblAnswerOption = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); + $courseId = api_get_course_int_id(); $sql = "SELECT position FROM $tblAnswerOption WHERE c_id = ".intval($courseId)." - AND id = ".intval($optionId); - $res = Database::query($sql); - - if (Database::num_rows($res) == 0) { - return 0; - } - - $data = Database::fetch_assoc($res); - - return $data['position']; - } - - /** - * return the correct id from c_quiz_question_option for question idAuto. - * - * @param $idAuto - * - * @return int - */ - public static function getCorrectAnswerOptionId($idAuto) - { - $tblAnswer = Database::get_course_table(TABLE_QUIZ_ANSWER); - $courseId = api_get_course_int_id(); + AND id = ".intval($optionId); + $res = Database::query($sql); + + if (Database::num_rows($res) == 0) { + return 0; + } + + $data = Database::fetch_assoc($res); + + return $data['position']; + } + + /** + * return the correct id from c_quiz_question_option for question idAuto. + * + * @param $idAuto + * + * @return int + */ + public static function getCorrectAnswerOptionId($idAuto) + { + $tblAnswer = Database::get_course_table(TABLE_QUIZ_ANSWER); + $courseId = api_get_course_int_id(); $sql = "SELECT correct FROM $tblAnswer WHERE c_id = ".intval($courseId)." - AND id_auto = ".intval($idAuto); - - $res = Database::query($sql); - $data = Database::fetch_assoc($res); - if (Database::num_rows($res) > 0) { - return $data['correct']; - } else { - return 0; - } - } - - /** - * return an array of exe info from track_e_attempt. - * - * @param $exeId - * @param int $questionId - * @param int $position - * - * @return array - */ - public static function getExerciseAttemptInfo($exeId, $questionId = -1, $position = -1) - { - $result = []; - $and = ''; - - if ($questionId >= 0) { - $and .= " AND question_id = ".intval($questionId); - } - if ($position >= 0) { - $and .= " AND position = ".intval($position); - } - - $tblExeAttempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT); - $cId = api_get_course_int_id(); + AND id_auto = ".intval($idAuto); + + $res = Database::query($sql); + $data = Database::fetch_assoc($res); + if (Database::num_rows($res) > 0) { + return $data['correct']; + } else { + return 0; + } + } + + /** + * return an array of exe info from track_e_attempt. + * + * @param $exeId + * @param int $questionId + * @param int $position + * + * @return array + */ + public static function getExerciseAttemptInfo($exeId, $questionId = -1, $position = -1) + { + $result = []; + $and = ''; + + if ($questionId >= 0) { + $and .= " AND question_id = ".intval($questionId); + } + if ($position >= 0) { + $and .= " AND position = ".intval($position); + } + + $tblExeAttempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT); + $cId = api_get_course_int_id(); $sql = "SELECT * FROM $tblExeAttempt WHERE c_id = $cId AND exe_id = $exeId - $and"; - - $res = Database::query($sql); - while ($data = Database::fetch_assoc($res)) { - $result[] = $data; - } - - return $result; - } - - public static function getNumberOfQuestionsForExeId($exeId) - { - $tableTrackEExercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); + $and"; + + $res = Database::query($sql); + while ($data = Database::fetch_assoc($res)) { + $result[] = $data; + } + + return $result; + } + + public static function getNumberOfQuestionsForExeId($exeId) + { + $tableTrackEExercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); $sql = "SELECT exe_exo_id FROM $tableTrackEExercise - WHERE exe_id=".intval($exeId); - $res = Database::query($sql); - $data = Database::fetch_assoc($res); - $exerciseId = $data['exe_exo_id']; - - $objectExercise = new Exercise(); - $objectExercise->read($exerciseId); - - return $objectExercise->get_count_question_list(); - } - - /** - * Display student chart results for these question types. - * - * @param $exeId - * - * @return string - */ - public static function displayStudentsChartResults($exeId, $objExercice) - { - $numberOfQuestions = self::getNumberOfQuestionsForExeId($exeId); - - $globalScoreList = MultipleAnswerTrueFalseDegreeCertainty::getColorNumberListForAttempt($exeId); - $html = MultipleAnswerTrueFalseDegreeCertainty::displayDegreeChart( - $globalScoreList, - 600, - get_lang('YourOverallResultForTheTest'), - 2, - 0, - true, - false, - false, - $numberOfQuestions - ) - ."
" - ; - - $previousAttemptId = MultipleAnswerTrueFalseDegreeCertainty::getPreviousAttemptId($exeId); - if ($previousAttemptId > 0) { - $previousAttemptScoreList = MultipleAnswerTrueFalseDegreeCertainty::getColorNumberListForAttempt( - $previousAttemptId - ); - $html .= MultipleAnswerTrueFalseDegreeCertainty::displayDegreeChart( - $previousAttemptScoreList, - 600, - get_lang('ForComparisonYourLastResultToThisTest'), - 2 - ) - ."
" - ; - } - - $categoryScoreList = MultipleAnswerTrueFalseDegreeCertainty::getColorNumberListForAttemptByCategory($exeId); - $html .= MultipleAnswerTrueFalseDegreeCertainty::displayDegreeChartByCategory( - $categoryScoreList, - get_lang('YourResultsByDiscipline'), - 1, $objExercice - ) - ."
" - ; - - return $html; - } - - - /** - * send mail to student with degre certainty result test - * @param $userId - * @param $objExercise - * @param $exeId - */ - public static function sendQuestionCertaintyNotification($userId, $objExercise, $exeId) - { - $userInfo = api_get_user_info($userId); - $recipient_name = api_get_person_name($userInfo['firstname'], - $userInfo['lastname'], - null, - PERSON_NAME_EMAIL_ADDRESS - ); - $emailTo = $userInfo['email']; - $senderName = api_get_person_name(api_get_setting('administratorName'), - api_get_setting('administratorSurname'), - null, - PERSON_NAME_EMAIL_ADDRESS - ); - $genericEmail = api_get_setting('emailAdministrator'); - - $subject = "[".get_lang('DoNotReply')."] " - .html_entity_decode(get_lang('ResultAccomplishedTest')." \"".$objExercise->title."\""); - - // message sended to the student - $message = get_lang('Dear').' '.$recipient_name.",

"; - $message .= get_lang('MessageQuestionCertainty'); - $exerciseLink = ""; - $titleExercice = $objExercise->title; - $message = str_replace('%exerTitle', $titleExercice, $message); - $message = str_replace('%webPath', api_get_path(WEB_PATH), $message); - $message = str_replace('%s', $exerciseLink, $message); - - // show histogram - require_once api_get_path(SYS_CODE_PATH) - ."exercise/multipleAnswerTrueFalseDegreeCertainty.php"; - $message .= MultipleAnswerTrueFalseDegreeCertainty::displayStudentsChartResults($exeId, $objExercise); - $message .= get_lang('KindRegards'); - - $message = api_preg_replace("/\\\n/", "", $message); - api_mail_html($recipient_name, - $emailTo, - $subject, - $message, - $senderName, - $genericEmail, - ['content-type' => 'html'] - ); - } - -} + WHERE exe_id=".intval($exeId); + $res = Database::query($sql); + $data = Database::fetch_assoc($res); + $exerciseId = $data['exe_exo_id']; + + $objectExercise = new Exercise(); + $objectExercise->read($exerciseId); + + return $objectExercise->get_count_question_list(); + } + + /** + * Display student chart results for these question types. + * + * @param $exeId + * + * @return string + */ + public static function displayStudentsChartResults($exeId, $objExercice) + { + $numberOfQuestions = self::getNumberOfQuestionsForExeId($exeId); + + $globalScoreList = MultipleAnswerTrueFalseDegreeCertainty::getColorNumberListForAttempt($exeId); + $html = MultipleAnswerTrueFalseDegreeCertainty::displayDegreeChart( + $globalScoreList, + 600, + get_lang('YourOverallResultForTheTest'), + 2, + 0, + true, + false, + false, + $numberOfQuestions + ) + ."
" + ; + + $previousAttemptId = MultipleAnswerTrueFalseDegreeCertainty::getPreviousAttemptId($exeId); + if ($previousAttemptId > 0) { + $previousAttemptScoreList = MultipleAnswerTrueFalseDegreeCertainty::getColorNumberListForAttempt( + $previousAttemptId + ); + $html .= MultipleAnswerTrueFalseDegreeCertainty::displayDegreeChart( + $previousAttemptScoreList, + 600, + get_lang('ForComparisonYourLastResultToThisTest'), + 2 + ) + ."
" + ; + } + + $categoryScoreList = MultipleAnswerTrueFalseDegreeCertainty::getColorNumberListForAttemptByCategory($exeId); + $html .= MultipleAnswerTrueFalseDegreeCertainty::displayDegreeChartByCategory( + $categoryScoreList, + get_lang('YourResultsByDiscipline'), + 1, $objExercice + ) + ."
" + ; + + return $html; + } + + /** + * send mail to student with degre certainty result test. + * + * @param $userId + * @param $objExercise + * @param $exeId + */ + public static function sendQuestionCertaintyNotification($userId, $objExercise, $exeId) + { + $userInfo = api_get_user_info($userId); + $recipient_name = api_get_person_name($userInfo['firstname'], + $userInfo['lastname'], + null, + PERSON_NAME_EMAIL_ADDRESS + ); + $emailTo = $userInfo['email']; + $senderName = api_get_person_name(api_get_setting('administratorName'), + api_get_setting('administratorSurname'), + null, + PERSON_NAME_EMAIL_ADDRESS + ); + $genericEmail = api_get_setting('emailAdministrator'); + + $subject = "[".get_lang('DoNotReply')."] " + .html_entity_decode(get_lang('ResultAccomplishedTest')." \"".$objExercise->title."\""); + + // message sended to the student + $message = get_lang('Dear').' '.$recipient_name.",

"; + $message .= get_lang('MessageQuestionCertainty'); + $exerciseLink = "
"; + $titleExercice = $objExercise->title; + $message = str_replace('%exerTitle', $titleExercice, $message); + $message = str_replace('%webPath', api_get_path(WEB_PATH), $message); + $message = str_replace('%s', $exerciseLink, $message); + + // show histogram + require_once api_get_path(SYS_CODE_PATH) + ."exercise/multipleAnswerTrueFalseDegreeCertainty.php"; + $message .= MultipleAnswerTrueFalseDegreeCertainty::displayStudentsChartResults($exeId, $objExercise); + $message .= get_lang('KindRegards'); + + $message = api_preg_replace("/\\\n/", "", $message); + api_mail_html($recipient_name, + $emailTo, + $subject, + $message, + $senderName, + $genericEmail, + ['content-type' => 'html'] + ); + } +} diff --git a/main/inc/ajax/exercise.ajax.php b/main/inc/ajax/exercise.ajax.php index 311580e9b4..fd2fcb27ca 100755 --- a/main/inc/ajax/exercise.ajax.php +++ b/main/inc/ajax/exercise.ajax.php @@ -524,7 +524,6 @@ switch ($action) { $objQuestionTmp = Question::read($my_question_id, $course_id); if ($objQuestionTmp->type == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) { - $myChoiceDegreeCertainty = isset($choiceDegreeCertainty[$my_question_id]) ? $choiceDegreeCertainty[$my_question_id] : null; } diff --git a/main/inc/lib/exercise.lib.php b/main/inc/lib/exercise.lib.php index cc85c12492..328ec66e3c 100644 --- a/main/inc/lib/exercise.lib.php +++ b/main/inc/lib/exercise.lib.php @@ -27,8 +27,9 @@ class ExerciseLib * @param bool $show_comment * @param bool $show_answers * - * @return bool|int * @throws \Exception + * + * @return bool|int */ public static function showQuestion( $exercise, @@ -2841,7 +2842,7 @@ HOTSPOT; $score = float_format($score, 1, $decimalSeparator, $thousandSeparator); $weight = float_format($weight, 1, $decimalSeparator, $thousandSeparator); } - + $html = ''; if ($show_percentage) { $percentageSign = '%'; @@ -3877,7 +3878,8 @@ EOT; } /** - * Get the number of questions with answers + * Get the number of questions with answers. + * * @param int $question_id * @param int $exercise_id * @param string $course_code @@ -3969,7 +3971,8 @@ EOT; } /** - * Get number of answers to hotspot questions + * Get number of answers to hotspot questions. + * * @param int $answer_id * @param int $question_id * @param int $exercise_id @@ -4324,7 +4327,8 @@ EOT; } /** - * Return an HTML select menu with the student groups + * Return an HTML select menu with the student groups. + * * @param string $name is the name and the id of the