Fix fill in blanks errors see #2053

- Use a hash of the value (sha1) instead of doing value="my text "
pull/2487/head
jmontoyaa 8 years ago
parent 8400dd6f8c
commit b9b2f12066
  1. 3
      main/exercise/answer.class.php
  2. 84
      main/exercise/exercise.class.php
  3. 351
      main/exercise/fill_blanks.class.php
  4. 39
      main/inc/ajax/exercise.ajax.php
  5. 73
      main/inc/lib/exercise.lib.php

@ -345,6 +345,7 @@ class Answer
/** /**
* return array answer by id else return a bool * return array answer by id else return a bool
* @param integer $auto_id * @param integer $auto_id
* @return array
*/ */
public function selectAnswerByAutoId($auto_id) public function selectAnswerByAutoId($auto_id)
{ {
@ -492,7 +493,7 @@ class Answer
* *
* @author Olivier Brouckaert * @author Olivier Brouckaert
* @param - integer $id - answer ID * @param - integer $id - answer ID
* @param integer $id
* @return integer - answer weighting * @return integer - answer weighting
*/ */
public function selectWeighting($id) public function selectWeighting($id)

@ -3779,7 +3779,7 @@ class Exercise
$str = $answerFromDatabase = Database::result($result, 0, 'answer'); $str = $answerFromDatabase = Database::result($result, 0, 'answer');
} }
if ($saved_results == false && strpos($str, 'font color') !== false) { if ($saved_results == false && strpos($answerFromDatabase, 'font color') !== false) {
// the question is encoded like this // the question is encoded like this
// [A] B [C] D [E] F::10,10,10@1 // [A] B [C] D [E] F::10,10,10@1
// number 1 before the "@" means that is a switchable fill in blank question // number 1 before the "@" means that is a switchable fill in blank question
@ -3891,7 +3891,7 @@ class Exercise
$totalScore += $answerWeighting[$i]; $totalScore += $answerWeighting[$i];
// adds the word in green at the end of the string // adds the word in green at the end of the string
$answer .= $user_tags[$i]; $answer .= $user_tags[$i];
} elseif (!empty ($user_tags[$i])) { } elseif (!empty($user_tags[$i])) {
// else if the word entered by the student IS NOT the same as the one defined by the professor // else if the word entered by the student IS NOT the same as the one defined by the professor
// adds the word in red at the end of the string, and strikes it // adds the word in red at the end of the string, and strikes it
$answer .= '<font color="red"><s>'.$user_tags[$i].'</s></font>'; $answer .= '<font color="red"><s>'.$user_tags[$i].'</s></font>';
@ -3916,7 +3916,7 @@ class Exercise
); );
$switchableAnswerSet = $listCorrectAnswers['switchable']; $switchableAnswerSet = $listCorrectAnswers['switchable'];
$answerWeighting = $listCorrectAnswers['tabweighting']; $answerWeighting = $listCorrectAnswers['weighting'];
// user choices is an array $choice // user choices is an array $choice
// get existing user data in n the BDD // get existing user data in n the BDD
@ -3925,15 +3925,15 @@ class Exercise
$answerFromDatabase, $answerFromDatabase,
true true
); );
$choice = $listStudentResults['studentanswer']; $choice = $listStudentResults['student_answer'];
} }
// loop other all blanks words // loop other all blanks words
if (!$switchableAnswerSet) { if (!$switchableAnswerSet) {
// not switchable answer, must be in the same place than teacher order // not switchable answer, must be in the same place than teacher order
for ($i = 0; $i < count($listCorrectAnswers['tabwords']); $i++) { for ($i = 0; $i < count($listCorrectAnswers['words']); $i++) {
$studentAnswer = isset($choice[$i]) ? $choice[$i] : ''; $studentAnswer = isset($choice[$i]) ? $choice[$i] : '';
$correctAnswer = $listCorrectAnswers['tabwords'][$i]; $correctAnswer = $listCorrectAnswers['words'][$i];
// This value is the user input, not escaped while correct answer is escaped by fckeditor // This value is the user input, not escaped while correct answer is escaped by fckeditor
// Works with cyrillic alphabet and when using ">" chars see #7718 #7610 #7618 // Works with cyrillic alphabet and when using ">" chars see #7718 #7610 #7618
@ -3943,30 +3943,62 @@ class Exercise
} }
$isAnswerCorrect = 0; $isAnswerCorrect = 0;
if (FillBlanks::isGoodStudentAnswer($studentAnswer, $correctAnswer)) { if (FillBlanks::isStudentAnswerGood($studentAnswer, $correctAnswer, $from_database)) {
// gives the related weighting to the student // gives the related weighting to the student
$questionScore += $answerWeighting[$i]; $questionScore += $answerWeighting[$i];
// increments total score // increments total score
$totalScore += $answerWeighting[$i]; $totalScore += $answerWeighting[$i];
$isAnswerCorrect = 1; $isAnswerCorrect = 1;
} }
$listCorrectAnswers['studentanswer'][$i] = $studentAnswer;
$listCorrectAnswers['studentscore'][$i] = $isAnswerCorrect; $studentAnswerToShow = $studentAnswer;
$type = FillBlanks::getFillTheBlankAnswerType($correctAnswer);
if ($type == FillBlanks::FILL_THE_BLANK_MENU) {
$listMenu = FillBlanks::getFillTheBlankMenuAnswers($correctAnswer, false);
if ($studentAnswer != '') {
foreach ($listMenu as $item) {
if (sha1($item) == $studentAnswer) {
$studentAnswerToShow = $item;
}
}
}
}
$listCorrectAnswers['student_answer'][$i] = $studentAnswerToShow;
$listCorrectAnswers['student_score'][$i] = $isAnswerCorrect;
} }
} else { } else {
// switchable answer // switchable answer
$listStudentAnswerTemp = $choice; $listStudentAnswerTemp = $choice;
$listTeacherAnswerTemp = $listCorrectAnswers['tabwords']; $listTeacherAnswerTemp = $listCorrectAnswers['words'];
// for every teacher answer, check if there is a student answer // for every teacher answer, check if there is a student answer
for ($i = 0; $i < count($listStudentAnswerTemp); $i++) { for ($i = 0; $i < count($listStudentAnswerTemp); $i++) {
$studentAnswer = trim($listStudentAnswerTemp[$i]); $studentAnswer = trim($listStudentAnswerTemp[$i]);
$studentAnswerToShow = $studentAnswer;
$found = false; $found = false;
for ($j = 0; $j < count($listTeacherAnswerTemp); $j++) { for ($j = 0; $j < count($listTeacherAnswerTemp); $j++) {
$correctAnswer = $listTeacherAnswerTemp[$j]; $correctAnswer = $listTeacherAnswerTemp[$j];
$type = FillBlanks::getFillTheBlankAnswerType($correctAnswer);
if ($type == FillBlanks::FILL_THE_BLANK_MENU) {
$listMenu = FillBlanks::getFillTheBlankMenuAnswers($correctAnswer, false);
if (!empty($studentAnswer)) {
//var_dump($listMenu, $correctAnswer);
foreach ($listMenu as $key => $item) {
if ($key == $correctAnswer) {
$studentAnswerToShow = $item;
break;
}
}
}
}
if (!$found) { if (!$found) {
if (FillBlanks::isGoodStudentAnswer( if (FillBlanks::isStudentAnswerGood(
$studentAnswer, $studentAnswer,
$correctAnswer $correctAnswer,
$from_database
) )
) { ) {
$questionScore += $answerWeighting[$i]; $questionScore += $answerWeighting[$i];
@ -3976,17 +4008,21 @@ class Exercise
} }
} }
} }
$listCorrectAnswers['studentanswer'][$i] = $studentAnswer; $listCorrectAnswers['student_answer'][$i] = $studentAnswerToShow;
if (!$found) { if (!$found) {
$listCorrectAnswers['studentscore'][$i] = 0; $listCorrectAnswers['student_score'][$i] = 0;
} else { } else {
$listCorrectAnswers['studentscore'][$i] = 1; $listCorrectAnswers['student_score'][$i] = 1;
} }
} }
} }
$answer = FillBlanks::getAnswerInStudentAttempt( $answer = FillBlanks::getAnswerInStudentAttempt(
$listCorrectAnswers $listCorrectAnswers
); );
if( $saved_results) {
//var_dump($listCorrectAnswers);
}
} }
break; break;
case CALCULATED_ANSWER: case CALCULATED_ANSWER:
@ -4025,13 +4061,15 @@ class Exercise
$answer .= $temp; $answer .= $temp;
break; break;
} }
if ($from_database) { if ($from_database) {
$queryfill = "SELECT answer FROM ".$TBL_TRACK_ATTEMPT." $sql = "SELECT answer FROM ".$TBL_TRACK_ATTEMPT."
WHERE WHERE
exe_id = '".$exeId."' AND exe_id = '".$exeId."' AND
question_id= ".intval($questionId); question_id = ".intval($questionId);
$resfill = Database::query($queryfill); $result = Database::query($sql);
$str = Database::result($resfill, 0, 'answer'); $str = Database::result($result, 0, 'answer');
api_preg_match_all('#\[([^[]*)\]#', $str, $arr); api_preg_match_all('#\[([^[]*)\]#', $str, $arr);
$str = str_replace('\r\n', '', $str); $str = str_replace('\r\n', '', $str);
$choice = $arr[1]; $choice = $arr[1];
@ -4103,8 +4141,8 @@ class Exercise
WHERE WHERE
exe_id = $exeId AND exe_id = $exeId AND
question_id= ".$questionId; question_id= ".$questionId;
$resq = Database::query($sql); $result = Database::query($sql);
$data = Database::fetch_array($resq); $data = Database::fetch_array($result);
$choice = $data['answer']; $choice = $data['answer'];
$choice = str_replace('\r\n', '', $choice); $choice = str_replace('\r\n', '', $choice);

@ -10,13 +10,13 @@
**/ **/
class FillBlanks extends Question class FillBlanks extends Question
{ {
public static $typePicture = 'fill_in_blanks.png';
public static $explanationLangVar = 'FillBlanks';
const FILL_THE_BLANK_STANDARD = 0; const FILL_THE_BLANK_STANDARD = 0;
const FILL_THE_BLANK_MENU = 1; const FILL_THE_BLANK_MENU = 1;
const FILL_THE_BLANK_SEVERAL_ANSWER = 2; const FILL_THE_BLANK_SEVERAL_ANSWER = 2;
public static $typePicture = 'fill_in_blanks.png';
public static $explanationLangVar = 'FillBlanks';
/** /**
* Constructor * Constructor
*/ */
@ -32,7 +32,7 @@ class FillBlanks extends Question
*/ */
public function createAnswersForm($form) public function createAnswersForm($form)
{ {
$defaults = array(); $defaults = [];
if (!empty($this->id)) { if (!empty($this->id)) {
$objectAnswer = new Answer($this->id); $objectAnswer = new Answer($this->id);
$answer = $objectAnswer->selectAnswer(1); $answer = $objectAnswer->selectAnswer(1);
@ -42,10 +42,10 @@ class FillBlanks extends Question
} else { } else {
$defaults['multiple_answer'] = 0; $defaults['multiple_answer'] = 0;
} }
//take the complete string except after the last '::' // Take the complete string except after the last '::'
$defaults['answer'] = $listAnswersInfo['text']; $defaults['answer'] = $listAnswersInfo['text'];
$defaults['select_separator'] = $listAnswersInfo['blankseparatornumber']; $defaults['select_separator'] = $listAnswersInfo['blank_separator_number'];
$blankSeparatorNumber = $listAnswersInfo['blankseparatornumber']; $blankSeparatorNumber = $listAnswersInfo['blank_separator_number'];
} else { } else {
$defaults['answer'] = get_lang('DefaultTextInBlanks'); $defaults['answer'] = get_lang('DefaultTextInBlanks');
$defaults['select_separator'] = 0; $defaults['select_separator'] = 0;
@ -54,20 +54,18 @@ class FillBlanks extends Question
$blankSeparatorStart = self::getStartSeparator($blankSeparatorNumber); $blankSeparatorStart = self::getStartSeparator($blankSeparatorNumber);
$blankSeparatorEnd = self::getEndSeparator($blankSeparatorNumber); $blankSeparatorEnd = self::getEndSeparator($blankSeparatorNumber);
$setWeightAndSize = ''; $setWeightAndSize = '';
if (isset($listAnswersInfo) && count($listAnswersInfo['tabweighting']) > 0) { if (isset($listAnswersInfo) && count($listAnswersInfo['weighting']) > 0) {
foreach ($listAnswersInfo['tabweighting'] as $i => $weighting) { foreach ($listAnswersInfo['weighting'] as $i => $weighting) {
$setWeightAndSize .= 'document.getElementById("weighting['.$i.']").value = "'.$weighting.'";'; $setWeightAndSize .= 'document.getElementById("weighting['.$i.']").value = "'.$weighting.'";';
} }
foreach ($listAnswersInfo['tabinputsize'] as $i => $sizeOfInput) { foreach ($listAnswersInfo['input_size'] as $i => $sizeOfInput) {
$setWeightAndSize .= 'document.getElementById("sizeofinput['.$i.']").value = "'.$sizeOfInput.'";'; $setWeightAndSize .= 'document.getElementById("sizeofinput['.$i.']").value = "'.$sizeOfInput.'";';
$setWeightAndSize .= 'document.getElementById("samplesize['.$i.']").style.width = "'.$sizeOfInput.'px";'; $setWeightAndSize .= 'document.getElementById("samplesize['.$i.']").style.width = "'.$sizeOfInput.'px";';
} }
} }
echo '<script> echo '<script>
var firstTime = true; var firstTime = true;
var originalOrder = new Array(); var originalOrder = new Array();
var blankSeparatorStart = "'.$blankSeparatorStart.'"; var blankSeparatorStart = "'.$blankSeparatorStart.'";
@ -97,13 +95,16 @@ class FillBlanks extends Question
// disable the save button, if not blanks have been created // disable the save button, if not blanks have been created
$("button").attr("disabled", "disabled"); $("button").attr("disabled", "disabled");
$("#defineoneblank").show(); $("#defineoneblank").show();
var blanks = answer.match(eval(blanksRegexp)); var blanks = answer.match(eval(blanksRegexp));
var fields = "<div class=\"form-group \">"; var fields = "<div class=\"form-group \">";
fields += "<label class=\"col-sm-2 control-label\">'.get_lang('Weighting').'</label>"; fields += "<label class=\"col-sm-2 control-label\"></label>";
fields += "<div class=\"col-sm-8\">"; fields += "<div class=\"col-sm-8\">";
fields += "<table>"; fields += "<table class=\"data_table\">";
fields += "<tr><th style=\"padding:0 20px\">'.get_lang("WordTofind").'</th><th style=\"padding:0 20px\">'.get_lang("QuestionWeighting").'</th><th style=\"padding:0 20px\">'.get_lang("BlankInputSize").'</th></tr>"; fields += "<tr><th style=\"width:220px\">'.get_lang("WordTofind").'</th>";
fields += "<th style=\"width:50px\">'.get_lang("QuestionWeighting").'</th>";
fields += "<th>'.get_lang("BlankInputSize").'</th></tr>";
if (blanks != null) { if (blanks != null) {
for (var i=0; i < blanks.length; i++) { for (var i=0; i < blanks.length; i++) {
@ -133,15 +134,16 @@ class FillBlanks extends Question
var value = document.getElementById("weighting["+i+"]").value; var value = document.getElementById("weighting["+i+"]").value;
} else { } else {
var value = "1"; var value = "1";
} }
var blanksWithColor = trimBlanksBetweenSeparator(blanks[i], blankSeparatorStart, blankSeparatorEnd, 1);
fields += "<tr>"; fields += "<tr>";
fields += "<td>"+blanks[i]+"</td>"; fields += "<td>"+blanksWithColor+"</td>";
fields += "<td><input style=\"width:35px\" value=\""+value+"\" type=\"text\" id=\"weighting["+i+"]\" name=\"weighting["+i+"]\" /></td>"; fields += "<td><input class=\"form-control\" style=\"width:60px\" value=\""+value+"\" type=\"text\" id=\"weighting["+i+"]\" name=\"weighting["+i+"]\" /></td>";
fields += "<td>"; fields += "<td>";
fields += "<input class=\"btn btn-default\" type=\"button\" value=\"-\" onclick=\"changeInputSize(-1, "+i+")\">&nbsp;"; fields += "<input class=\"btn btn-default\" type=\"button\" value=\"-\" onclick=\"changeInputSize(-1, "+i+")\">&nbsp;";
fields += "<input class=\"btn btn-default\" type=\"button\" value=\"+\" onclick=\"changeInputSize(1, "+i+")\">&nbsp;"; fields += "<input class=\"btn btn-default\" type=\"button\" value=\"+\" onclick=\"changeInputSize(1, "+i+")\">&nbsp;";
fields += "<input class=\"sample\" id=\"samplesize["+i+"]\" data-btoa=\""+btoaValue+"\" type=\"text\" value=\""+textValue+"\" style=\"width:"+inputSize+"px\" disabled=disabled />"; fields += "&nbsp;&nbsp;<input class=\"sample\" id=\"samplesize["+i+"]\" data-btoa=\""+btoaValue+"\" type=\"text\" value=\""+textValue+"\" style=\"width:"+inputSize+"px\" disabled=disabled />";
fields += "<input id=\"sizeofinput["+i+"]\" type=\"hidden\" value=\""+inputSize+"\" name=\"sizeofinput["+i+"]\" />"; fields += "<input id=\"sizeofinput["+i+"]\" type=\"hidden\" value=\""+inputSize+"\" name=\"sizeofinput["+i+"]\" />";
fields += "</td>"; fields += "</td>";
fields += "</tr>"; fields += "</tr>";
@ -152,7 +154,8 @@ class FillBlanks extends Question
} }
} }
document.getElementById("blanks_weighting").innerHTML = fields + "</table></div></div>"; document.getElementById("blanks_weighting").innerHTML = fields + "</table></div></div>";
$(originalOrder).each(function(i, data) { $(originalOrder).each(function(i, data) {
if (firstTime == false) { if (firstTime == false) {
value = data.value; value = data.value;
@ -235,7 +238,7 @@ class FillBlanks extends Question
$("#samplesize\\\["+inIdNum+"\\\]").outerWidth(newWidth); $("#samplesize\\\["+inIdNum+"\\\]").outerWidth(newWidth);
$("#sizeofinput\\\["+inIdNum+"\\\]").attr("value", newWidth); $("#sizeofinput\\\["+inIdNum+"\\\]").attr("value", newWidth);
updateOrder(blanks); updateOrder(blanks);
} }
function removeForbiddenChars(inTxt) function removeForbiddenChars(inTxt)
@ -279,27 +282,44 @@ class FillBlanks extends Question
// this function is the same than the PHP one // this function is the same than the PHP one
// if modify it modify the php one getAllowedSeparator // if modify it modify the php one getAllowedSeparator
function getSeparatorFromNumber(innumber) function getSeparatorFromNumber(number)
{ {
tabSeparator = new Array(); var separator = new Array();
tabSeparator[0] = new Array("[", "]"); separator[0] = new Array("[", "]");
tabSeparator[1] = new Array("{", "}"); separator[1] = new Array("{", "}");
tabSeparator[2] = new Array("(", ")"); separator[2] = new Array("(", ")");
tabSeparator[3] = new Array("*", "*"); separator[3] = new Array("*", "*");
tabSeparator[4] = new Array("#", "#"); separator[4] = new Array("#", "#");
tabSeparator[5] = new Array("%", "%"); separator[5] = new Array("%", "%");
tabSeparator[6] = new Array("$", "$"); separator[6] = new Array("$", "$");
return tabSeparator[innumber]; return separator[number];
} }
function trimBlanksBetweenSeparator(inTxt, inSeparatorStart, inSeparatorEnd) function trimBlanksBetweenSeparator(inTxt, inSeparatorStart, inSeparatorEnd, addColor)
{ {
var result = inTxt var result = inTxt
result = result.replace(inSeparatorStart, ""); result = result.replace(inSeparatorStart, "");
result = result.replace(inSeparatorEnd, ""); result = result.replace(inSeparatorEnd, "");
result = result.trim(); result = result.trim();
if (addColor == 1) {
var resultParts = result.split("|");
var partsToString = "";
resultParts.forEach(function(item, index) {
if (index == 0) {
item = "<b><font style=\"color:green\"> " + item +"</font></b>";
}
if (index < resultParts.length - 1) {
item = item + " | ";
}
partsToString += item;
});
result = partsToString;
}
return inSeparatorStart+result+inSeparatorEnd; return inSeparatorStart+result+inSeparatorEnd;
} }
</script>'; </script>';
// answer // answer
@ -321,14 +341,15 @@ class FillBlanks extends Question
$form->addElement( $form->addElement(
'select', 'select',
'select_separator', 'select_separator',
get_lang("SelectFillTheBlankSeparator"), get_lang('SelectFillTheBlankSeparator'),
self::getAllowedSeparatorForSelect(), self::getAllowedSeparatorForSelect(),
' id="select_separator" style="width:150px" onchange="changeBlankSeparator()" ' ' id="select_separator" style="width:150px" class="selectpicker" onchange="changeBlankSeparator()" '
); );
$form->addLabel( $form->addLabel(
null, null,
'<input type="button" onclick="updateBlanks()" value="'.get_lang('RefreshBlanks').'" class="btn btn-default" />' '<input type="button" onclick="updateBlanks()" value="'.get_lang('RefreshBlanks').'" class="btn btn-default" />'
); );
$form->addHtml('<div id="blanks_weighting"></div>'); $form->addHtml('<div id="blanks_weighting"></div>');
global $text; global $text;
@ -424,7 +445,7 @@ class FillBlanks extends Question
$answer .= ","; $answer .= ",";
} }
// calculate the global weighting for the question // calculate the global weighting for the question
$this -> weighting += $form->getSubmitValue('weighting['.$i.']'); $this->weighting += (float) $form->getSubmitValue('weighting['.$i.']');
} }
// input width // input width
@ -497,8 +518,9 @@ class FillBlanks extends Question
$displayForStudent, $displayForStudent,
$inBlankNumber $inBlankNumber
) { ) {
$inTabTeacherSolution = $listAnswersInfo['tabwords']; $inTabTeacherSolution = $listAnswersInfo['words'];
$inTeacherSolution = $inTabTeacherSolution[$inBlankNumber]; $inTeacherSolution = $inTabTeacherSolution[$inBlankNumber];
switch (self::getFillTheBlankAnswerType($inTeacherSolution)) { switch (self::getFillTheBlankAnswerType($inTeacherSolution)) {
case self::FILL_THE_BLANK_MENU: case self::FILL_THE_BLANK_MENU:
$selected = ''; $selected = '';
@ -512,19 +534,14 @@ class FillBlanks extends Question
$resultOptions = ['' => '--']; $resultOptions = ['' => '--'];
foreach ($listMenu as $item) { foreach ($listMenu as $item) {
$item = self::trimOption($item); $resultOptions[sha1($item)] = $item;
$resultOptions[$item] = $item;
} }
for ($k = 0; $k < count($listMenu); $k++) { //var_dump($resultOptions, $correctItem);
if ($correctItem == $listMenu[$k]) {
$selected = $k;
break; foreach ($resultOptions as $key => $value) {
} if ($correctItem == $value) {
// if in teacher view, display the first item by default, which is the right answer $selected = $key;
if ($k == 0 && !$displayForStudent) {
$selected = $k;
break; break;
} }
@ -555,12 +572,17 @@ class FillBlanks extends Question
return $result; return $result;
} }
/**
* Removes double spaces between words
* @param string $text
* @return string
*/
private static function trimOption($text) private static function trimOption($text)
{ {
$converted = strtr($text, array_flip(get_html_translation_table(HTML_ENTITIES, ENT_QUOTES))); $text = trim($text);
$trimmed = trim($converted, chr(0xC2).chr(0xA0).' '); $text = preg_replace("/\s+/", " ", $text);
return $trimmed; return $text;
} }
/** /**
@ -574,8 +596,13 @@ class FillBlanks extends Question
public static function getFillTheBlankMenuAnswers($correctAnswer, $displayForStudent) public static function getFillTheBlankMenuAnswers($correctAnswer, $displayForStudent)
{ {
$list = api_preg_split("/\|/", $correctAnswer); $list = api_preg_split("/\|/", $correctAnswer);
foreach ($list as &$item) {
$item = self::trimOption($item);
$item = api_html_entity_decode($item);
}
// The list is always in the same order, there's no option to allow or disable shuffle options.
if ($displayForStudent) { if ($displayForStudent) {
shuffle($list); shuffle_assoc($list);
} }
return $list; return $list;
@ -620,33 +647,49 @@ class FillBlanks extends Question
* Return true if student answer is right according to the correctAnswer * Return true if student answer is right according to the correctAnswer
* it is not as simple as equality, because of the type of Fill The Blank question * it is not as simple as equality, because of the type of Fill The Blank question
* eg : studentAnswer = 'Un' and correctAnswer = 'Un||1||un' * eg : studentAnswer = 'Un' and correctAnswer = 'Un||1||un'
* @param string $studentAnswer [studentanswer] of the info array of the answer field * @param string $studentAnswer [student_answer] of the info array of the answer field
* @param string $correctAnswer [tabwords] of the info array of the answer field * @param string $correctAnswer [words] of the info array of the answer field
* * @param bool $fromDatabase
* @return bool * @return bool
*/ */
public static function isGoodStudentAnswer($studentAnswer, $correctAnswer) public static function isStudentAnswerGood($studentAnswer, $correctAnswer, $fromDatabase = false)
{ {
$result = false;
switch (self::getFillTheBlankAnswerType($correctAnswer)) { switch (self::getFillTheBlankAnswerType($correctAnswer)) {
case self::FILL_THE_BLANK_MENU: case self::FILL_THE_BLANK_MENU:
$listMenu = self::getFillTheBlankMenuAnswers($correctAnswer, false); $listMenu = self::getFillTheBlankMenuAnswers($correctAnswer, false);
$result = self::trimOption($listMenu[0]) == $studentAnswer; if ($studentAnswer != '' && isset($listMenu[0])) {
// First item is always the correct one.
$item = $listMenu[0];
if (!$fromDatabase) {
$item = sha1($item);
}
if ($item === $studentAnswer) {
$result = true;
}
}
break; break;
case self::FILL_THE_BLANK_SEVERAL_ANSWER: case self::FILL_THE_BLANK_SEVERAL_ANSWER:
// the answer must be one of the choice made // the answer must be one of the choice made
$listSeveral = self::getFillTheBlankSeveralAnswers($correctAnswer); $listSeveral = self::getFillTheBlankSeveralAnswers($correctAnswer);
$listSeveral = array_map(
$listSeveral = array_map(function($item) { function ($item) {
return self::trimOption($item); return self::trimOption($item);
}, $listSeveral); },
$listSeveral
);
$result = in_array($studentAnswer, $listSeveral); $result = in_array($studentAnswer, $listSeveral);
break; break;
case self::FILL_THE_BLANK_STANDARD: case self::FILL_THE_BLANK_STANDARD:
default: default:
$correctAnswer = api_html_entity_decode($correctAnswer);
$studentAnswer = htmlspecialchars($studentAnswer);
$result = $studentAnswer == self::trimOption($correctAnswer); $result = $studentAnswer == self::trimOption($correctAnswer);
break; break;
} }
//var_dump($result);
return $result; return $result;
} }
@ -658,9 +701,9 @@ class FillBlanks extends Question
*/ */
public static function getFillTheBlankAnswerType($correctAnswer) public static function getFillTheBlankAnswerType($correctAnswer)
{ {
if (api_strpos($correctAnswer, "|") && !api_strpos($correctAnswer, "||")) { if (api_strpos($correctAnswer, '|') && !api_strpos($correctAnswer, '||')) {
return self::FILL_THE_BLANK_MENU; return self::FILL_THE_BLANK_MENU;
} elseif (api_strpos($correctAnswer, "||")) { } elseif (api_strpos($correctAnswer, '||')) {
return self::FILL_THE_BLANK_SEVERAL_ANSWER; return self::FILL_THE_BLANK_SEVERAL_ANSWER;
} else { } else {
return self::FILL_THE_BLANK_STANDARD; return self::FILL_THE_BLANK_STANDARD;
@ -674,20 +717,20 @@ class FillBlanks extends Question
* *
* @return array of information about the answer * @return array of information about the answer
*/ */
public static function getAnswerInfo($userAnswer = "", $isStudentAnswer = false) public static function getAnswerInfo($userAnswer = '', $isStudentAnswer = false)
{ {
$listAnswerResults = array(); $listAnswerResults = [];
$listAnswerResults['text'] = ''; $listAnswerResults['text'] = '';
$listAnswerResults['wordsCount'] = 0; $listAnswerResults['words_count'] = 0;
$listAnswerResults['tabwordsbracket'] = array(); $listAnswerResults['words_with_bracket'] = [];
$listAnswerResults['tabwords'] = array(); $listAnswerResults['words'] = [];
$listAnswerResults['tabweighting'] = array(); $listAnswerResults['weighting'] = [];
$listAnswerResults['tabinputsize'] = array(); $listAnswerResults['input_size'] = [];
$listAnswerResults['switchable'] = ''; $listAnswerResults['switchable'] = '';
$listAnswerResults['studentanswer'] = array(); $listAnswerResults['student_answer'] = [];
$listAnswerResults['studentscore'] = array(); $listAnswerResults['student_score'] = [];
$listAnswerResults['blankseparatornumber'] = 0; $listAnswerResults['blank_separator_number'] = 0;
$listDoubleColon = array(); $listDoubleColon = [];
api_preg_match("/(.*)::(.*)$/s", $userAnswer, $listResult); api_preg_match("/(.*)::(.*)$/s", $userAnswer, $listResult);
@ -699,22 +742,22 @@ class FillBlanks extends Question
$listDoubleColon[] = $listResult[2]; $listDoubleColon[] = $listResult[2];
} }
$listAnswerResults['systemstring'] = $listDoubleColon[1]; $listAnswerResults['system_string'] = $listDoubleColon[1];
// make sure we only take the last bit to find special marks // Make sure we only take the last bit to find special marks
$listArobaseSplit = explode('@', $listDoubleColon[1]); $listArobaseSplit = explode('@', $listDoubleColon[1]);
if (count($listArobaseSplit) < 2) { if (count($listArobaseSplit) < 2) {
$listArobaseSplit[1] = ''; $listArobaseSplit[1] = '';
} }
// take the complete string except after the last '::' // Take the complete string except after the last '::'
$listDetails = explode(":", $listArobaseSplit[0]); $listDetails = explode(":", $listArobaseSplit[0]);
// < number of item after the ::[score]:[size]:[separator_id]@ , here there are 3 // < number of item after the ::[score]:[size]:[separator_id]@ , here there are 3
if (count($listDetails) < 3) { if (count($listDetails) < 3) {
$listWeightings = explode(',', $listDetails[0]); $listWeightings = explode(',', $listDetails[0]);
$listSizeOfInput = array(); $listSizeOfInput = [];
for ($i = 0; $i < count($listWeightings); $i++) { for ($i = 0; $i < count($listWeightings); $i++) {
$listSizeOfInput[] = 200; $listSizeOfInput[] = 200;
} }
@ -726,27 +769,27 @@ class FillBlanks extends Question
} }
$listAnswerResults['text'] = $listDoubleColon[0]; $listAnswerResults['text'] = $listDoubleColon[0];
$listAnswerResults['tabweighting'] = $listWeightings; $listAnswerResults['weighting'] = $listWeightings;
$listAnswerResults['tabinputsize'] = $listSizeOfInput; $listAnswerResults['input_size'] = $listSizeOfInput;
$listAnswerResults['switchable'] = $listArobaseSplit[1]; $listAnswerResults['switchable'] = $listArobaseSplit[1];
$listAnswerResults['blankseparatorstart'] = self::getStartSeparator($blankSeparatorNumber); $listAnswerResults['blank_separator_start'] = self::getStartSeparator($blankSeparatorNumber);
$listAnswerResults['blankseparatorend'] = self::getEndSeparator($blankSeparatorNumber); $listAnswerResults['blank_separator_end'] = self::getEndSeparator($blankSeparatorNumber);
$listAnswerResults['blankseparatornumber'] = $blankSeparatorNumber; $listAnswerResults['blank_separator_number'] = $blankSeparatorNumber;
$blankCharStart = self::getStartSeparator($blankSeparatorNumber); $blankCharStart = self::getStartSeparator($blankSeparatorNumber);
$blankCharEnd = self::getEndSeparator($blankSeparatorNumber); $blankCharEnd = self::getEndSeparator($blankSeparatorNumber);
$blankCharStartForRegexp = self::escapeForRegexp($blankCharStart); $blankCharStartForRegexp = self::escapeForRegexp($blankCharStart);
$blankCharEndForRegexp = self::escapeForRegexp($blankCharEnd); $blankCharEndForRegexp = self::escapeForRegexp($blankCharEnd);
// get all blanks words // Get all blanks words
$listAnswerResults['wordsCount'] = api_preg_match_all( $listAnswerResults['words_count'] = api_preg_match_all(
'/'.$blankCharStartForRegexp.'[^'.$blankCharEndForRegexp.']*'.$blankCharEndForRegexp.'/', '/'.$blankCharStartForRegexp.'[^'.$blankCharEndForRegexp.']*'.$blankCharEndForRegexp.'/',
$listDoubleColon[0], $listDoubleColon[0],
$listWords $listWords
); );
if ($listAnswerResults['wordsCount'] > 0) { if ($listAnswerResults['words_count'] > 0) {
$listAnswerResults['tabwordsbracket'] = $listWords[0]; $listAnswerResults['words_with_bracket'] = $listWords[0];
// remove [ and ] in string // remove [ and ] in string
array_walk( array_walk(
$listWords[0], $listWords[0],
@ -759,10 +802,10 @@ class FillBlanks extends Question
}, },
array($blankCharStart, $blankCharEnd) array($blankCharStart, $blankCharEnd)
); );
$listAnswerResults['tabwords'] = $listWords[0]; $listAnswerResults['words'] = $listWords[0];
} }
// get all common words // Get all common words
$commonWords = api_preg_replace( $commonWords = api_preg_replace(
'/'.$blankCharStartForRegexp.'[^'.$blankCharEndForRegexp.']*'.$blankCharEndForRegexp.'/', '/'.$blankCharStartForRegexp.'[^'.$blankCharEndForRegexp.']*'.$blankCharEndForRegexp.'/',
"::", "::",
@ -771,32 +814,31 @@ class FillBlanks extends Question
// if student answer, the second [] is the student answer, // if student answer, the second [] is the student answer,
// the third is if student scored or not // the third is if student scored or not
$listBrackets = array(); $listBrackets = [];
$listWords = array(); $listWords = [];
if ($isStudentAnswer) { if ($isStudentAnswer) {
for ($i = 0; $i < count($listAnswerResults['tabwords']); $i++) { for ($i = 0; $i < count($listAnswerResults['words']); $i++) {
$listBrackets[] = $listAnswerResults['tabwordsbracket'][$i]; $listBrackets[] = $listAnswerResults['words_with_bracket'][$i];
$listWords[] = $listAnswerResults['tabwords'][$i]; $listWords[] = $listAnswerResults['words'][$i];
if ($i + 1 < count($listAnswerResults['tabwords'])) { if ($i + 1 < count($listAnswerResults['words'])) {
// should always be // should always be
$i++; $i++;
} }
$listAnswerResults['studentanswer'][] = $listAnswerResults['tabwords'][$i]; $listAnswerResults['student_answer'][] = $listAnswerResults['words'][$i];
if ($i + 1 < count($listAnswerResults['tabwords'])) { if ($i + 1 < count($listAnswerResults['words'])) {
// should always be // should always be
$i++; $i++;
} }
$listAnswerResults['studentscore'][] = $listAnswerResults['tabwords'][$i]; $listAnswerResults['student_score'][] = $listAnswerResults['words'][$i];
} }
$listAnswerResults['tabwords'] = $listWords; $listAnswerResults['words'] = $listWords;
$listAnswerResults['tabwordsbracket'] = $listBrackets; $listAnswerResults['words_with_bracket'] = $listBrackets;
// if we are in student view, we've got 3 times :::::: for common words // if we are in student view, we've got 3 times :::::: for common words
$commonWords = api_preg_replace("/::::::/", "::", $commonWords); $commonWords = api_preg_replace("/::::::/", "::", $commonWords);
} }
$listAnswerResults['commonwords'] = explode("::", $commonWords); $listAnswerResults['common_words'] = explode("::", $commonWords);
return $listAnswerResults; return $listAnswerResults;
} }
@ -838,7 +880,7 @@ class FillBlanks extends Question
$courseId = api_get_course_int_id(); $courseId = api_get_course_int_id();
// If no user has answered questions, no need to go further. Return empty array. // If no user has answered questions, no need to go further. Return empty array.
if (empty($studentsIdList)) { if (empty($studentsIdList)) {
return array(); return [];
} }
// request to have all the answers of student for this question // request to have all the answers of student for this question
// student may have doing it several time // student may have doing it several time
@ -860,29 +902,29 @@ class FillBlanks extends Question
'; ';
$res = Database::query($sql); $res = Database::query($sql);
$tabUserResult = array(); $tabUserResult = [];
// foreach attempts for all students starting with his older attempt // foreach attempts for all students starting with his older attempt
while ($data = Database::fetch_array($res)) { while ($data = Database::fetch_array($res)) {
$tabAnswer = self::getAnswerInfo($data['answer'], true); $tabAnswer = self::getAnswerInfo($data['answer'], true);
// for each bracket to find in this question // for each bracket to find in this question
foreach ($tabAnswer['studentanswer'] as $bracketNumber => $studentAnswer) { foreach ($tabAnswer['student_answer'] as $bracketNumber => $studentAnswer) {
if ($tabAnswer['studentanswer'][$bracketNumber] != '') { if ($tabAnswer['student_answer'][$bracketNumber] != '') {
// student has answered this bracket, cool // student has answered this bracket, cool
switch (self::getFillTheBlankAnswerType($tabAnswer['tabwords'][$bracketNumber])) { switch (self::getFillTheBlankAnswerType($tabAnswer['words'][$bracketNumber])) {
case self::FILL_THE_BLANK_MENU: case self::FILL_THE_BLANK_MENU:
// get the indice of the choosen answer in the menu // get the indice of the choosen answer in the menu
// we know that the right answer is the first entry of the menu, ie 0 // we know that the right answer is the first entry of the menu, ie 0
// (remember, menu entries are shuffled when taking the test) // (remember, menu entries are shuffled when taking the test)
$tabUserResult[$data['user_id']][$bracketNumber] = self::getFillTheBlankMenuAnswerNum( $tabUserResult[$data['user_id']][$bracketNumber] = self::getFillTheBlankMenuAnswerNum(
$tabAnswer['tabwords'][$bracketNumber], $tabAnswer['words'][$bracketNumber],
$tabAnswer['studentanswer'][$bracketNumber] $tabAnswer['student_answer'][$bracketNumber]
); );
break; break;
default: default:
if (self::isGoodStudentAnswer( if (self::isStudentAnswerGood(
$tabAnswer['studentanswer'][$bracketNumber], $tabAnswer['student_answer'][$bracketNumber],
$tabAnswer['tabwords'][$bracketNumber] $tabAnswer['words'][$bracketNumber]
) )
) { ) {
$tabUserResult[$data['user_id']][$bracketNumber] = 0; // right answer $tabUserResult[$data['user_id']][$bracketNumber] = 0; // right answer
@ -939,20 +981,20 @@ class FillBlanks extends Question
*/ */
public static function getAnswerInStudentAttempt($listWithStudentAnswer) public static function getAnswerInStudentAttempt($listWithStudentAnswer)
{ {
$separatorStart = $listWithStudentAnswer['blankseparatorstart']; $separatorStart = $listWithStudentAnswer['blank_separator_start'];
$separatorEnd = $listWithStudentAnswer['blankseparatorend']; $separatorEnd = $listWithStudentAnswer['blank_separator_end'];
// lets rebuild the sentence with [correct answer][student answer][answer is correct] // lets rebuild the sentence with [correct answer][student answer][answer is correct]
$result = ''; $result = '';
for ($i = 0; $i < count($listWithStudentAnswer['commonwords']) - 1; $i++) { for ($i = 0; $i < count($listWithStudentAnswer['common_words']) - 1; $i++) {
$result .= $listWithStudentAnswer['commonwords'][$i]; $result .= $listWithStudentAnswer['common_words'][$i];
$result .= $listWithStudentAnswer['tabwordsbracket'][$i]; $result .= $listWithStudentAnswer['words_with_bracket'][$i];
$result .= $separatorStart.$listWithStudentAnswer['studentanswer'][$i].$separatorEnd; $result .= $separatorStart.$listWithStudentAnswer['student_answer'][$i].$separatorEnd;
$result .= $separatorStart.$listWithStudentAnswer['studentscore'][$i].$separatorEnd; $result .= $separatorStart.$listWithStudentAnswer['student_score'][$i].$separatorEnd;
} }
$result .= $listWithStudentAnswer['commonwords'][$i]; $result .= $listWithStudentAnswer['common_words'][$i];
$result .= "::"; $result .= "::";
// add the system string // add the system string
$result .= $listWithStudentAnswer['systemstring']; $result .= $listWithStudentAnswer['system_string'];
return $result; return $result;
} }
@ -1038,17 +1080,15 @@ class FillBlanks extends Question
*/ */
public static function getAllowedSeparator() public static function getAllowedSeparator()
{ {
$fillBlanksAllowedSeparator = array( return [
array('[', ']'), ['[', ']'],
array('{', '}'), ['{', '}'],
array('(', ')'), ['(', ')'],
array('*', '*'), ['*', '*'],
array('#', '#'), ['#', '#'],
array('%', '%'), ['%', '%'],
array('$', '$'), ['$', '$'],
); ];
return $fillBlanksAllowedSeparator;
} }
/** /**
@ -1084,10 +1124,10 @@ class FillBlanks extends Question
*/ */
public static function getAllowedSeparatorForSelect() public static function getAllowedSeparatorForSelect()
{ {
$listResults = array(); $listResults = [];
$fillBlanksAllowedSeparator = self::getAllowedSeparator(); $allowedSeparator = self::getAllowedSeparator();
for ($i = 0; $i < count($fillBlanksAllowedSeparator); $i++) { foreach ($allowedSeparator as $part) {
$listResults[] = $fillBlanksAllowedSeparator[$i][0]."...".$fillBlanksAllowedSeparator[$i][1]; $listResults[] = $part[0]."...".$part[1];
} }
return $listResults; return $listResults;
@ -1142,19 +1182,19 @@ class FillBlanks extends Question
// rebuild the answer with good HTML style // rebuild the answer with good HTML style
// this is the student answer, right or wrong // this is the student answer, right or wrong
for ($i = 0; $i < count($listStudentAnswerInfo['studentanswer']); $i++) { for ($i = 0; $i < count($listStudentAnswerInfo['student_answer']); $i++) {
if ($listStudentAnswerInfo['studentscore'][$i] == 1) { if ($listStudentAnswerInfo['student_score'][$i] == 1) {
$listStudentAnswerInfo['studentanswer'][$i] = self::getHtmlRightAnswer( $listStudentAnswerInfo['student_answer'][$i] = self::getHtmlRightAnswer(
$listStudentAnswerInfo['studentanswer'][$i], $listStudentAnswerInfo['student_answer'][$i],
$listStudentAnswerInfo['tabwords'][$i], $listStudentAnswerInfo['words'][$i],
$feedbackType, $feedbackType,
$resultsDisabled, $resultsDisabled,
$showTotalScoreAndUserChoices $showTotalScoreAndUserChoices
); );
} else { } else {
$listStudentAnswerInfo['studentanswer'][$i] = self::getHtmlWrongAnswer( $listStudentAnswerInfo['student_answer'][$i] = self::getHtmlWrongAnswer(
$listStudentAnswerInfo['studentanswer'][$i], $listStudentAnswerInfo['student_answer'][$i],
$listStudentAnswerInfo['tabwords'][$i], $listStudentAnswerInfo['words'][$i],
$feedbackType, $feedbackType,
$resultsDisabled, $resultsDisabled,
$showTotalScoreAndUserChoices $showTotalScoreAndUserChoices
@ -1163,13 +1203,13 @@ class FillBlanks extends Question
} }
// rebuild the sentence with student answer inserted // rebuild the sentence with student answer inserted
for ($i = 0; $i < count($listStudentAnswerInfo['commonwords']); $i++) { for ($i = 0; $i < count($listStudentAnswerInfo['common_words']); $i++) {
$result .= isset($listStudentAnswerInfo['commonwords'][$i]) ? $listStudentAnswerInfo['commonwords'][$i] : ''; $result .= isset($listStudentAnswerInfo['common_words'][$i]) ? $listStudentAnswerInfo['common_words'][$i] : '';
$result .= isset($listStudentAnswerInfo['studentanswer'][$i]) ? $listStudentAnswerInfo['studentanswer'][$i] : ''; $result .= isset($listStudentAnswerInfo['student_answer'][$i]) ? $listStudentAnswerInfo['student_answer'][$i] : '';
} }
// the last common word (should be </p>) // the last common word (should be </p>)
$result .= isset($listStudentAnswerInfo['commonwords'][$i]) ? $listStudentAnswerInfo['commonwords'][$i] : ''; $result .= isset($listStudentAnswerInfo['common_words'][$i]) ? $listStudentAnswerInfo['common_words'][$i] : '';
return $result; return $result;
} }
@ -1254,7 +1294,9 @@ class FillBlanks extends Question
* return HTML code for correct answer * return HTML code for correct answer
* @param string $answer * @param string $answer
* @param string $correct * @param string $correct
* @param bool $resultsDisabled * @param string $feedbackType
* @param bool $resultsDisabled
* @param bool $showTotalScoreAndUserChoices
* *
* @return string * @return string
*/ */
@ -1279,6 +1321,7 @@ class FillBlanks extends Question
* return HTML code for wrong answer * return HTML code for wrong answer
* @param string $answer * @param string $answer
* @param string $correct * @param string $correct
* @param string $feedbackType
* @param bool $resultsDisabled * @param bool $resultsDisabled
* *
* @return string * @return string
@ -1308,13 +1351,13 @@ class FillBlanks extends Question
public static function isCorrect($answerText) public static function isCorrect($answerText)
{ {
$answerInfo = self::getAnswerInfo($answerText, true); $answerInfo = self::getAnswerInfo($answerText, true);
$correctAnswerList = $answerInfo['tabwords']; $correctAnswerList = $answerInfo['words'];
$studentAnswer = $answerInfo['studentanswer']; $studentAnswer = $answerInfo['student_answer'];
$isCorrect = true; $isCorrect = true;
foreach ($correctAnswerList as $i => $correctAnswer) { foreach ($correctAnswerList as $i => $correctAnswer) {
$isGoodStudentAnswer = self::isGoodStudentAnswer($studentAnswer[$i], $correctAnswer); $value = self::isStudentAnswerGood($studentAnswer[$i], $correctAnswer);
$isCorrect = $isCorrect && $isGoodStudentAnswer; $isCorrect = $isCorrect && $value;
} }
return $isCorrect; return $isCorrect;

@ -270,10 +270,10 @@ switch ($action) {
$learnpath_item_id = isset($_REQUEST['learnpath_item_id']) ? intval($_REQUEST['learnpath_item_id']) : 0; $learnpath_item_id = isset($_REQUEST['learnpath_item_id']) ? intval($_REQUEST['learnpath_item_id']) : 0;
// Attempt id. // Attempt id.
$exe_id = $_REQUEST['exe_id']; $exeId = $_REQUEST['exe_id'];
if ($debug) { if ($debug) {
error_log("exe_id = $exe_id"); error_log("exe_id = $exeId");
error_log("type = $type"); error_log("type = $type");
error_log("choice = ".print_r($choice, 1)." "); error_log("choice = ".print_r($choice, 1)." ");
error_log("hot_spot_coordinates = ".print_r($hot_spot_coordinates, 1)); error_log("hot_spot_coordinates = ".print_r($hot_spot_coordinates, 1));
@ -303,18 +303,18 @@ switch ($action) {
} }
// Getting information of the current exercise. // Getting information of the current exercise.
$exercise_stat_info = $objExercise->get_stat_track_exercise_info_by_exe_id($exe_id); $exercise_stat_info = $objExercise->get_stat_track_exercise_info_by_exe_id($exeId);
$exercise_id = $exercise_stat_info['exe_exo_id']; $exercise_id = $exercise_stat_info['exe_exo_id'];
$attemptList = array(); $attemptList = [];
// First time here we create an attempt (getting the exe_id). // First time here we create an attempt (getting the exe_id).
if (!empty($exercise_stat_info)) { if (!empty($exercise_stat_info)) {
// We know the user we get the exe_id. // We know the user we get the exe_id.
$exe_id = $exercise_stat_info['exe_id']; $exeId = $exercise_stat_info['exe_id'];
$total_score = $exercise_stat_info['exe_result']; $total_score = $exercise_stat_info['exe_result'];
// Getting the list of attempts // Getting the list of attempts
$attemptList = Event::getAllExerciseEventByExeId($exe_id); $attemptList = Event::getAllExerciseEventByExeId($exeId);
} }
// Updating Reminder algorithm. // Updating Reminder algorithm.
@ -341,7 +341,7 @@ switch ($action) {
} }
// No exe id? Can't save answer. // No exe id? Can't save answer.
if (empty($exe_id)) { if (empty($exeId)) {
// Fires an error. // Fires an error.
echo 'error'; echo 'error';
if ($debug) { if ($debug) {
@ -350,7 +350,7 @@ switch ($action) {
exit; exit;
} }
Session::write('exe_id', $exe_id); Session::write('exe_id', $exeId);
// Getting the total weight if the request is simple // Getting the total weight if the request is simple
$total_weight = 0; $total_weight = 0;
@ -383,9 +383,7 @@ switch ($action) {
$objQuestionTmp = Question::read($my_question_id, $course_id); $objQuestionTmp = Question::read($my_question_id, $course_id);
// Getting free choice data. // Getting free choice data.
if (($objQuestionTmp->type == FREE_ANSWER || $objQuestionTmp->type == ORAL_EXPRESSION) && if (in_array($objQuestionTmp->type, [FREE_ANSWER, ORAL_EXPRESSION]) && $type == 'all') {
$type == 'all'
) {
$my_choice = isset($_REQUEST['free_choice'][$my_question_id]) && !empty($_REQUEST['free_choice'][$my_question_id]) $my_choice = isset($_REQUEST['free_choice'][$my_question_id]) && !empty($_REQUEST['free_choice'][$my_question_id])
? $_REQUEST['free_choice'][$my_question_id] ? $_REQUEST['free_choice'][$my_question_id]
: null; : null;
@ -402,20 +400,19 @@ switch ($action) {
) { ) {
$hotspot_delineation_result = $_SESSION['hotspot_delineation_result'][$objExercise->selectId()][$my_question_id]; $hotspot_delineation_result = $_SESSION['hotspot_delineation_result'][$objExercise->selectId()][$my_question_id];
} }
if ($type == 'simple') { if ($type == 'simple') {
// Getting old attempt in order to decrees the total score. // Getting old attempt in order to decrees the total score.
$old_result = $objExercise->manage_answer( $old_result = $objExercise->manage_answer(
$exe_id, $exeId,
$my_question_id, $my_question_id,
null, null,
'exercise_show', 'exercise_show',
array(), [],
false, false,
true, true,
false, false,
$objExercise->selectPropagateNeg(), $objExercise->selectPropagateNeg(),
array() []
); );
// Removing old score. // Removing old score.
@ -425,10 +422,10 @@ switch ($action) {
// Deleting old attempt // Deleting old attempt
if (isset($attemptList) && !empty($attemptList[$my_question_id])) { if (isset($attemptList) && !empty($attemptList[$my_question_id])) {
if ($debug) { if ($debug) {
error_log("delete_attempt exe_id : $exe_id, my_question_id: $my_question_id"); error_log("delete_attempt exe_id : $exeId, my_question_id: $my_question_id");
} }
Event::delete_attempt( Event::delete_attempt(
$exe_id, $exeId,
api_get_user_id(), api_get_user_id(),
$course_id, $course_id,
$session_id, $session_id,
@ -436,7 +433,7 @@ switch ($action) {
); );
if ($objQuestionTmp->type == HOT_SPOT) { if ($objQuestionTmp->type == HOT_SPOT) {
Event::delete_attempt_hotspot( Event::delete_attempt_hotspot(
$exe_id, $exeId,
api_get_user_id(), api_get_user_id(),
$course_id, $course_id,
$session_id, $session_id,
@ -453,7 +450,7 @@ switch ($action) {
// We're inside *one* question. Go through each possible answer for this question // We're inside *one* question. Go through each possible answer for this question
$result = $objExercise->manage_answer( $result = $objExercise->manage_answer(
$exe_id, $exeId,
$my_question_id, $my_question_id,
$my_choice, $my_choice,
'exercise_result', 'exercise_result',
@ -477,7 +474,7 @@ switch ($action) {
$now = time(); $now = time();
if ($type == 'all') { if ($type == 'all') {
$exercise_stat_info = $objExercise->get_stat_track_exercise_info_by_exe_id($exe_id); $exercise_stat_info = $objExercise->get_stat_track_exercise_info_by_exe_id($exeId);
} }
$key = ExerciseLib::get_time_control_key( $key = ExerciseLib::get_time_control_key(
@ -501,7 +498,7 @@ switch ($action) {
$_SESSION['duration_time'][$key] = time(); $_SESSION['duration_time'][$key] = time();
Event::updateEventExercise( Event::updateEventExercise(
$exe_id, $exeId,
$objExercise->selectId(), $objExercise->selectId(),
$total_score, $total_score,
$total_weight, $total_weight,

@ -132,8 +132,8 @@ class ExerciseLib
$x = 1; $x = 1;
//mark letters for each answer //mark letters for each answer
$letter = 'A'; $letter = 'A';
$answer_matching = array(); $answer_matching = [];
$cpt1 = array(); $cpt1 = [];
for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) { for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) {
$answerCorrect = $objAnswerTmp->isCorrect($answerId); $answerCorrect = $objAnswerTmp->isCorrect($answerId);
$numAnswer = $objAnswerTmp->selectAutoId($answerId); $numAnswer = $objAnswerTmp->selectAutoId($answerId);
@ -292,8 +292,6 @@ class ExerciseLib
$objQuestionTmp->selectDescription() $objQuestionTmp->selectDescription()
); );
$hidingClass = 'hide-reading-answers'; $hidingClass = 'hide-reading-answers';
}
if ($answerType == READING_COMPREHENSION) {
$s .= Display::div( $s .= Display::div(
$objQuestionTmp->selectTitle(), $objQuestionTmp->selectTitle(),
['class' => 'question_title '.$hidingClass] ['class' => 'question_title '.$hidingClass]
@ -305,7 +303,7 @@ class ExerciseLib
$answerCorrect = $objAnswerTmp->isCorrect($answerId); $answerCorrect = $objAnswerTmp->isCorrect($answerId);
$numAnswer = $objAnswerTmp->selectAutoId($answerId); $numAnswer = $objAnswerTmp->selectAutoId($answerId);
$comment = $objAnswerTmp->selectComment($answerId); $comment = $objAnswerTmp->selectComment($answerId);
$attributes = array(); $attributes = [];
switch ($answerType) { switch ($answerType) {
case UNIQUE_ANSWER: case UNIQUE_ANSWER:
@ -592,16 +590,16 @@ class ExerciseLib
$listAnswerInfo = FillBlanks::getAnswerInfo($answer); $listAnswerInfo = FillBlanks::getAnswerInfo($answer);
// Correct answers // Correct answers
$correctAnswerList = $listAnswerInfo['tabwords']; $correctAnswerList = $listAnswerInfo['words'];
// Student's answer // Student's answer
$studentAnswerList = array(); $studentAnswerList = [];
if (isset($user_choice[0]['answer'])) { if (isset($user_choice[0]['answer'])) {
$arrayStudentAnswer = FillBlanks::getAnswerInfo( $arrayStudentAnswer = FillBlanks::getAnswerInfo(
$user_choice[0]['answer'], $user_choice[0]['answer'],
true true
); );
$studentAnswerList = $arrayStudentAnswer['studentanswer']; $studentAnswerList = $arrayStudentAnswer['student_answer'];
} }
// If the question must be shown with the answer (in page exercise/admin.php) for teacher preview // If the question must be shown with the answer (in page exercise/admin.php) for teacher preview
@ -613,18 +611,18 @@ class ExerciseLib
if (!empty($correctAnswerList) && !empty($studentAnswerList)) { if (!empty($correctAnswerList) && !empty($studentAnswerList)) {
$answer = ''; $answer = '';
for ($i = 0; $i < count($listAnswerInfo['commonwords']) - 1; $i++) { for ($i = 0; $i < count($listAnswerInfo['common_words']) - 1; $i++) {
// display the common word // display the common word
$answer .= $listAnswerInfo['commonwords'][$i]; $answer .= $listAnswerInfo['common_words'][$i];
// display the blank word // display the blank word
$correctItem = $listAnswerInfo['tabwords'][$i]; $correctItem = $listAnswerInfo['words'][$i];
if (isset($studentAnswerList[$i])) { if (isset($studentAnswerList[$i])) {
// If student already started this test and answered this question, // If student already started this test and answered this question,
// fill the blank with his previous answers // fill the blank with his previous answers
// may be "" if student viewed the question, but did not fill the blanks // may be "" if student viewed the question, but did not fill the blanks
$correctItem = $studentAnswerList[$i]; $correctItem = $studentAnswerList[$i];
} }
$attributes['style'] = "width:".$listAnswerInfo['tabinputsize'][$i]."px"; $attributes['style'] = "width:".$listAnswerInfo['input_size'][$i]."px";
$answer .= FillBlanks::getFillTheBlankHtml( $answer .= FillBlanks::getFillTheBlankHtml(
$current_item, $current_item,
$questionId, $questionId,
@ -637,15 +635,15 @@ class ExerciseLib
); );
} }
// display the last common word // display the last common word
$answer .= $listAnswerInfo['commonwords'][$i]; $answer .= $listAnswerInfo['common_words'][$i];
} else { } else {
// display empty [input] with the right width for student to fill it // display empty [input] with the right width for student to fill it
$answer = ''; $answer = '';
for ($i = 0; $i < count($listAnswerInfo['commonwords']) - 1; $i++) { for ($i = 0; $i < count($listAnswerInfo['common_words']) - 1; $i++) {
// display the common words // display the common words
$answer .= $listAnswerInfo['commonwords'][$i]; $answer .= $listAnswerInfo['common_words'][$i];
// display the blank word // display the blank word
$attributes["style"] = "width:".$listAnswerInfo['tabinputsize'][$i]."px"; $attributes['style'] = "width:".$listAnswerInfo['input_size'][$i]."px";
$answer .= FillBlanks::getFillTheBlankHtml( $answer .= FillBlanks::getFillTheBlankHtml(
$current_item, $current_item,
$questionId, $questionId,
@ -658,7 +656,7 @@ class ExerciseLib
); );
} }
// display the last common word // display the last common word
$answer .= $listAnswerInfo['commonwords'][$i]; $answer .= $listAnswerInfo['common_words'][$i];
} }
$s .= $answer; $s .= $answer;
break; break;
@ -3946,25 +3944,23 @@ EOT;
/** /**
* Display the exercise results * Display the exercise results
* @param Exercise $objExercise * @param Exercise $objExercise
* @param int $exe_id * @param int $exeId
* @param bool $save_user_result save users results (true) or just show the results (false) * @param bool $save_user_result save users results (true) or just show the results (false)
* @param string $remainingMessage * @param string $remainingMessage
*/ */
public static function displayQuestionListByAttempt( public static function displayQuestionListByAttempt(
$objExercise, $objExercise,
$exe_id, $exeId,
$save_user_result = false, $save_user_result = false,
$remainingMessage = '' $remainingMessage = ''
) { ) {
$origin = api_get_origin(); $origin = api_get_origin();
// Getting attempt info // Getting attempt info
$exercise_stat_info = $objExercise->get_stat_track_exercise_info_by_exe_id( $exercise_stat_info = $objExercise->get_stat_track_exercise_info_by_exe_id($exeId);
$exe_id
);
// Getting question list // Getting question list
$question_list = array(); $question_list = [];
if (!empty($exercise_stat_info['data_tracking'])) { if (!empty($exercise_stat_info['data_tracking'])) {
$question_list = explode(',', $exercise_stat_info['data_tracking']); $question_list = explode(',', $exercise_stat_info['data_tracking']);
} else { } else {
@ -4078,6 +4074,7 @@ EOT;
$exerciseResult = null; $exerciseResult = null;
$exerciseResultCoordinates = null; $exerciseResultCoordinates = null;
$delineationResults = null; $delineationResults = null;
if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) { if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
$loadChoiceFromSession = true; $loadChoiceFromSession = true;
$fromDatabase = false; $fromDatabase = false;
@ -4091,9 +4088,8 @@ EOT;
// Loop over all question to show results for each of them, one by one // Loop over all question to show results for each of them, one by one
if (!empty($question_list)) { if (!empty($question_list)) {
foreach ($question_list as $questionId) { foreach ($question_list as $questionId) {
// creates a temporary Question object // Creates a temporary Question object
$objQuestionTmp = Question::read($questionId); $objQuestionTmp = Question::read($questionId);
// This variable came from exercise_submit_modal.php // This variable came from exercise_submit_modal.php
ob_start(); ob_start();
$choice = null; $choice = null;
@ -4105,7 +4101,7 @@ EOT;
// We're inside *one* question. Go through each possible answer for this question // We're inside *one* question. Go through each possible answer for this question
$result = $objExercise->manage_answer( $result = $objExercise->manage_answer(
$exe_id, $exeId,
$questionId, $questionId,
$choice, $choice,
'exercise_result', 'exercise_result',
@ -4169,17 +4165,16 @@ EOT;
$category_list['none']['total'] += $my_total_weight; $category_list['none']['total'] += $my_total_weight;
} }
if ($objExercise->selectPropagateNeg() == 0 && if ($objExercise->selectPropagateNeg() == 0 && $my_total_score < 0) {
$my_total_score < 0
) {
$my_total_score = 0; $my_total_score = 0;
} }
$comnt = null; $comnt = null;
if ($show_results) { if ($show_results) {
$comnt = Event::get_comments($exe_id, $questionId); $comnt = Event::get_comments($exeId, $questionId);
$teacherAudio = ExerciseLib::getOralFeedbackAudio( $teacherAudio = ExerciseLib::getOralFeedbackAudio(
$exe_id, $exeId,
$questionId, $questionId,
api_get_user_id() api_get_user_id()
); );
@ -4197,6 +4192,7 @@ EOT;
} }
} }
$score = [];
if ($show_results) { if ($show_results) {
$score = [ $score = [
'result' => self::show_score( 'result' => self::show_score(
@ -4208,10 +4204,8 @@ EOT;
'pass' => $my_total_score >= $my_total_weight ? true : false, 'pass' => $my_total_score >= $my_total_weight ? true : false,
'score' => $my_total_score, 'score' => $my_total_score,
'weight' => $my_total_weight, 'weight' => $my_total_weight,
'comments' => $comnt, 'comments' => $comnt
]; ];
} else {
$score = [];
} }
if (in_array($objQuestionTmp->type, [FREE_ANSWER, ORAL_EXPRESSION, ANNOTATION])) { if (in_array($objQuestionTmp->type, [FREE_ANSWER, ORAL_EXPRESSION, ANNOTATION])) {
@ -4238,7 +4232,10 @@ EOT;
$question_content .= '</div>'; $question_content .= '</div>';
} }
if (!$show_only_score) { if (!$show_only_score) {
$exercise_content .= Display::div(Display::panel($question_content),array('class' => 'question-panel')); $exercise_content .= Display::div(
Display::panel($question_content),
['class' => 'question-panel']
);
} }
} // end foreach() block that loops over all questions } // end foreach() block that loops over all questions
} }
@ -4258,10 +4255,10 @@ EOT;
if (!empty($category_list) && ($show_results || $show_only_score)) { if (!empty($category_list) && ($show_results || $show_only_score)) {
// Adding total // Adding total
$category_list['total'] = array( $category_list['total'] = [
'score' => $total_score, 'score' => $total_score,
'total' => $total_weight 'total' => $total_weight
); ];
echo TestCategory::get_stats_table_by_attempt( echo TestCategory::get_stats_table_by_attempt(
$objExercise->id, $objExercise->id,
$category_list $category_list
@ -4323,7 +4320,7 @@ EOT;
'end', 'end',
$question_list_answers, $question_list_answers,
$origin, $origin,
$exe_id, $exeId,
$total_score, $total_score,
$total_weight $total_weight
); );

Loading…
Cancel
Save