Merge branch 'chamilo19102remote2' of https://github.com/baelmyhu/chamilo-lms into baelmyhu-chamilo19102remote2

1.9.x
Yannick Warnier 11 years ago
commit 02d3aa4b23
  1. 166
      main/exercice/exercise.class.php
  2. 171
      main/exercice/exercise.lib.php
  3. 801
      main/exercice/fill_blanks.class.php
  4. 3
      main/exercice/stats.php
  5. 15
      main/inc/lib/exercise_show_functions.lib.php

@ -2464,144 +2464,74 @@ class Exercise
break;
// for fill in the blanks
case FILL_IN_BLANKS:
// the question is encoded like this
// [A] B [C] D [E] F::10,10,10@1
// number 1 before the "@" means that is a switchable fill in blank question
// [A] B [C] D [E] F::10,10,10@ or [A] B [C] D [E] F::10,10,10
// means that is a normal fill blank question
// first we explode the "::"
$pre_array = explode('::', $answer);
// is switchable fill blank or not
$last = count($pre_array) - 1;
$is_set_switchable = explode('@', $pre_array[$last]);
$switchable_answer_set = false;
if (isset ($is_set_switchable[1]) && $is_set_switchable[1] == 1) {
$switchable_answer_set = true;
}
$answer = '';
for ($k = 0; $k < $last; $k++) {
$answer .= $pre_array[$k];
}
// splits weightings that are joined with a comma
$answerWeighting = explode(',', $is_set_switchable[0]);
// insert the student result in the track_e_attempt table, field answer
// $answer is the answer like in the c_quiz_answer table for the question
// student datas are choice[]
// we save the answer because it will be modified
$temp = $answer;
$answer = '';
$j = 0;
//initialise answer tags
$user_tags = $correct_tags = $real_text = array();
// the loop will stop at the end of the text
while (1) {
// quits the loop if there are no more blanks (detect '[')
if (($pos = api_strpos($temp, '[')) === false) {
// adds the end of the text
$answer = $temp;
$real_text[] = $answer;
break; //no more "blanks", quit the loop
}
// adds the piece of text that is before the blank
//and ends with '[' into a general storage array
$real_text[] = api_substr($temp, 0, $pos +1);
$answer .= api_substr($temp, 0, $pos +1);
//take the string remaining (after the last "[" we found)
$temp = api_substr($temp, $pos +1);
// quit the loop if there are no more blanks, and update $pos to the position of next ']'
if (($pos = api_strpos($temp, ']')) === false) {
// adds the end of the text
$answer .= $temp;
break;
}
$listCorrectAnswers = FillBlanks::getAnswerInfo($answer);
$switchableAnswerSet = $listCorrectAnswers["switchable"];
$answerWeighting = $listCorrectAnswers["tabweighting"];
// user choices is an array $choice
// get existing user data in n the BDD
if ($from_database) {
$queryfill = "SELECT answer FROM ".$TBL_TRACK_ATTEMPT."
WHERE
exe_id = '".$exeId."' AND
question_id= ".intval($questionId)."";
$queryfill = "SELECT answer
FROM $TBL_TRACK_ATTEMPT
WHERE exe_id = $exeId
AND question_id= ".intval($questionId);
$resfill = Database::query($queryfill);
$str = Database::result($resfill,0,'answer');
api_preg_match_all('#\[([^[]*)\]#', $str, $arr);
$str = str_replace('\r\n', '', $str);
$choice = $arr[1];
if (isset($choice[$j])) {
$tmp = api_strrpos($choice[$j], ' / ');
$choice[$j] = api_substr($choice[$j], 0, $tmp);
$choice[$j] = trim($choice[$j]);
// Needed to let characters ' and " to work as part of an answer
$choice[$j] = stripslashes($choice[$j]);
} else {
$choice[$j] = null;
}
} else {
// This value is the user input, not escaped while correct answer is escaped by fckeditor
$choice[$j] = api_htmlentities(trim($choice[$j]));
}
$user_tags[] = $choice[$j];
//put the contents of the [] answer tag into correct_tags[]
$correct_tags[] = api_substr($temp, 0, $pos);
$j++;
$temp = api_substr($temp, $pos +1);
$listStudentResults = FillBlanks::getAnswerInfo($str, true);
$choice = $listStudentResults['studentanswer'];
}
$answer = '';
$real_correct_tags = $correct_tags;
$chosen_list = array();
for ($i = 0; $i < count($real_correct_tags); $i++) {
if ($i == 0) {
$answer .= $real_text[0];
}
if (!$switchable_answer_set) {
// Needed to parse ' and " characters
$user_tags[$i] = stripslashes($user_tags[$i]);
if ($correct_tags[$i] == $user_tags[$i]) {
// loop other all blanks words
if (!$switchableAnswerSet) {
// not switchable answer, must be in the same place than teacher order
for ($i=0; $i < count($listCorrectAnswers['tabwords']); $i++) {
$studentAnswer = trim($choice[$i]);
$correctAnswer = $listCorrectAnswers['tabwords'][$i];
$isAnswerCorrect = 0;
if (FillBlanks::isGoodStudentAnswer($studentAnswer, $correctAnswer)) {
// gives the related weighting to the student
$questionScore += $answerWeighting[$i];
// increments total score
$totalScore += $answerWeighting[$i];
// adds the word in green at the end of the string
$answer .= $correct_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
// adds the word in red at the end of the string, and strikes it
$answer .= '<font color="red"><s>' . $user_tags[$i] . '</s></font>';
} else {
// adds a tabulation if no word has been typed by the student
$answer .= ''; // remove &nbsp; that causes issue
$isAnswerCorrect = 1;
}
$listCorrectAnswers['studentanswer'][$i] = $studentAnswer;
$listCorrectAnswers['studentscore'][$i] = $isAnswerCorrect;
}
} else {
// switchable fill in the blanks
if (in_array($user_tags[$i], $correct_tags)) {
$chosen_list[] = $user_tags[$i];
$correct_tags = array_diff($correct_tags, $chosen_list);
// gives the related weighting to the student
// switchable answer
$listStudentAsnwerTemp = $choice;
$listTeacherAnswerTemp = $listCorrectAnswers['tabwords'];
$listBadAnswerIndice = array();
// for every teacher answer, check if there is a student answer
for ($i=0; $i < count($listStudentAsnwerTemp); $i++) {
$studentAnswer = trim($listStudentAsnwerTemp[$i]);
$found = false;
for ($j=0; $j < count($listTeacherAnswerTemp); $j++) {
$correctAnswer = $listTeacherAnswerTemp[$j];
if (!$found) {
if (FillBlanks::isGoodStudentAnswer($studentAnswer, $correctAnswer)) {
$questionScore += $answerWeighting[$i];
// increments total score
$totalScore += $answerWeighting[$i];
// adds the word in green at the end of the string
$answer .= $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
// adds the word in red at the end of the string, and strikes it
$answer .= '<font color="red"><s>' . $user_tags[$i] . '</s></font>';
} else {
// adds a tabulation if no word has been typed by the student
$answer .= ''; // remove &nbsp; that causes issue
$listTeacherAnswerTemp[$j] = "";
$found = true;
}
}
// adds the correct word, followed by ] to close the blank
$answer .= ' / <font color="green"><b>' . $real_correct_tags[$i] . '</b></font>]';
if (isset($real_text[$i +1])) {
$answer .= $real_text[$i +1];
}
$listCorrectAnswers['studentanswer'][$i] = $studentAnswer;
if (!$found) {
$listCorrectAnswers['studentscore'][$i] = 0;
} else {
$listCorrectAnswers['studentscore'][$i] = 1;
}
}
}
$answer = FillBlanks::getAnswerInStudentAttempt($listCorrectAnswers);
break;
// for calculated answer
case CALCULATED_ANSWER:

@ -436,124 +436,73 @@ function showQuestion(
$s .='</tr>';
} elseif ($answerType == FILL_IN_BLANKS) {
/*
* In the FILL_IN_BLANKS test
* you mustn't have [ and ] in the textarea
* you mustn't have :: in the textarea
* the text to find mustn't be empty or contains only spaces
* the text to find mustn't contains HTML tags
* the text to find mustn't contains char "
*/
// display the question, with field empty, for student to fill it,
// or filled to display the answer in the Question preview of the exercice/admin.php page
$displayForStudent = true;
$listAnswerInformations = FillBlanks::getAnswerInfo($answer);
$separatorStartRegexp = FillBlanks::escapeForRegexp($listAnswerInformations['blankseparatorstart']);
$separatorEndRegexp = FillBlanks::escapeForRegexp($listAnswerInformations['blankseparatorend']);
list($answer) = explode('::', $answer);
// $correct_answer_list array of array with correct anwsers 0=> [0=>[\p] 1=>[plop]]
api_preg_match_all('/\[[^]]+\]/', $answer, $correct_answer_list);
//Correct answer
$correctAnswerList = $listAnswerInformations['tabwords'];
// get student answer to display it if student go back to previous fillBlank answer question in a test
//Student's answer
$studentAnswerList = array();
if (isset($user_choice[0]['answer'])) {
api_preg_match_all('/\[[^]]+\]/', $user_choice[0]['answer'], $student_answer_list);
$student_answer_list_tobecleaned = $student_answer_list[0];
$student_answer_list = array();
// here we got the student answer in a test
// let's clean up the results
/*
Array
(
[0] => Array
(
[0] => [<font color="red"><s>yer</s></font> / <font color="green"><b>ici</b></font>]
[1] => [<font color="red"><s>plop</s></font> / <font color="green"><b>/p</b></font>]
)
)
*/
for ($i=0; $i < count($student_answer_list_tobecleaned); $i++) {
$answer_corrected = $student_answer_list_tobecleaned[$i];
/*
* we got if student answer is wrong
* [<font color="red"><s>rrr</s></font> / <font color="green"><b>/p</b></font>]
* or if student answer is good
* [plop / <font color="green"><b>plop</b></font>]
* or if student didn't answer []
*/
$answer_corrected = api_preg_replace('| / <font color="green"><b>.*$|', '', $answer_corrected);
/*
* we got [<font color="red"><s>rrr</s></font> or [plop or [
*/
$answer_corrected = api_preg_replace('/^\[/', '', $answer_corrected);
/*
* we got <font color="red"><s>rrr</s></font> or plop
* non breakable spaces &nbsp;&nbsp;&nbsp; from /main/exercice/exercise.class.php have been removed l 2391 and l 2370
*/
$answer_corrected = api_preg_replace('|^<font color="red"><s>|', '', $answer_corrected);
$answer_corrected = api_preg_replace('|</s></font>$|', '', $answer_corrected);
$answer_corrected = '['.$answer_corrected.']';
/*
* we got [rrr] or [plop] or []
*/
$student_answer_list[] = $answer_corrected;
}
$arrayStudentAnswer = FillBlanks::getAnswerInfo($user_choice[0]['answer'], true);
$studentAnswerList = $arrayStudentAnswer['studentanswer'];
}
// If display preview of answer in test view for exemple, set the student answer to the correct answers
// If display the question with answer (in page exercice/admin.php) for teacher preview
// set the student-answer to the correct answer
if ($debug_mark_answer) {
// contain the rights answers surronded with brackets
$student_answer_list = $correct_answer_list[0];
$studentAnswerList = $correctAnswerList;
$displayForStudent = false;
}
/*
Split the response by bracket
tab_comments is an array with text surrounding the text to find
we add a space before and after the answer_question to be sure to
have a block of text before and after [xxx] patterns
so we have n text to find ([xxx]) and n+1 block of texts before,
between and after the text to find
*/
$tab_comments = api_preg_split('/\[[^]]+\]/', ' '.$answer.' ');
if (!empty($correct_answer_list) && !empty($student_answer_list)) {
if (!empty($correctAnswerList) && !empty($studentAnswerList)) {
$answer = "";
$i = 0;
foreach ($student_answer_list as $student_item) {
// remove surronding brackets
$student_response = api_substr($student_item, 1, api_strlen($student_item) - 2);
$size = strlen($student_item);
$attributes['class'] = detectInputAppropriateClass($size);
$answer .= $tab_comments[$i].
Display::input(
'text',
"choice[$questionId][]",
$student_response,
$attributes
);
$i++;
}
$answer .= $tab_comments[$i];
for ($i = 0; $i < count($listAnswerInformations["commonwords"]) - 1; $i++) {
// display the common word
$answer .= $listAnswerInformations["commonwords"][$i];
// display the blank word
$correctItem = $listAnswerInformations["tabwords"][$i];
$correctItemRegexp = $correctItem;
// replace / with \/ to allow the preg_replace bellow and all the regexp char
$correctItemRegexp = FillBlanks::getRegexpProtected($correctItemRegexp);
if (isset($studentAnswerList[$i])) {
// student already start this test and this question
// fill the blank with his previous answers
// may be "" if student did the question, but not fill the blanks
$correctItem = $studentAnswerList[$i];
}
$attributes["style"] = "width:".$listAnswerInformations["tabinputsize"][$i]."px";
$answer .= FillBlanks::getFillTheBlankHtml($separatorStartRegexp, $separatorEndRegexp, $correctItemRegexp, $questionId, $correctItem, $attributes, $answer, $listAnswerInformations, $displayForStudent, $i);
}
// display the last common word
$answer .= $listAnswerInformations["commonwords"][$i];
} else {
// display exercise with empty input fields
// every [xxx] are replaced with an empty input field
foreach ($correct_answer_list[0] as $item) {
$size = strlen($item);
$attributes['class'] = detectInputAppropriateClass($size);
$answer = str_replace(
$item,
Display::input('text', "choice[$questionId][]", '', $attributes),
$answer
);
}
/*$answer = api_preg_replace(
'/\[[^]]+\]/',
Display::input(
'text',
"choice[$questionId][]",
'',
$attributes
), $answer);*/
// display empty [input] with the right width for student to fill it
$separatorStartRegexp = FillBlanks::escapeForRegexp($listAnswerInformations['blankseparatorstart']);
$separatorEndRegexp = FillBlanks::escapeForRegexp($listAnswerInformations['blankseparatorend']);
$answer = "";
for ($i = 0; $i < count($listAnswerInformations["commonwords"]) - 1; $i++) {
// display the common words
$answer .= $listAnswerInformations["commonwords"][$i];
// display the blank word
$attributes["style"] = "width:".$listAnswerInformations["tabinputsize"][$i]."px";
$correctItem = $listAnswerInformations["tabwords"][$i];
$correctItemRegexp = $correctItem;
// replace / with \/ to allow the preg_replace bellow and all the regexp char
$correctItemRegexp = FillBlanks::getRegexpProtected($correctItemRegexp);
$answer .= FillBlanks::getFillTheBlankHtml($separatorStartRegexp, $separatorEndRegexp, $correctItemRegexp, $questionId, '', $attributes, $answer, $listAnswerInformations, $displayForStudent, $i);
}
// display the last common word
$answer .= $listAnswerInformations["commonwords"][$i];
}
$s .= $answer;
} elseif ($answerType == CALCULATED_ANSWER) {
/*
* In the CALCULATED_ANSWER test
@ -2250,7 +2199,7 @@ function get_student_stats_by_question($question_id, $exercise_id, $course_code
* @param int $session_id
* @return int
*/
function get_number_students_question_with_answer_count($question_id, $exercise_id, $course_code, $session_id)
function get_number_students_question_with_answer_count($question_id, $exercise_id, $course_code, $session_id, $questionType = '')
{
$track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
$track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
@ -2262,6 +2211,18 @@ function get_number_students_question_with_answer_count($question_id, $exercise_
$course_code = Database::escape_string($course_code);
$session_id = intval($session_id);
if ($questionType == FILL_IN_BLANKS) {
$listStudentsId = array();
$listAllStudentInfo = CourseManager::get_student_list_from_course_code(api_get_course_id(), true);
foreach ($listAllStudentInfo as $i => $listStudentInfo ) {
$listStudentsId[] = $listStudentInfo['user_id'];
}
$listFillTheBlankResult = getFillTheBlankTabResult($exercise_id, $question_id, $listStudentsId, '1970-01-01', '3000-01-01');
return getNbResultFillBlankAll($listFillTheBlankResult);
}
if (empty($session_id)) {
$courseCondition = "
INNER JOIN $courseUser cu

@ -13,6 +13,10 @@ class FillBlanks extends Question
static $typePicture = 'fill_in_blanks.png';
static $explanationLangVar = 'FillBlanks';
const FILL_THE_BLANK_STANDARD = 0;
const FILL_THE_BLANK_MENU = 1;
const FILL_THE_BLANK_SEVERAL_ANSWER = 2;
/**
* Constructor
*/
@ -27,42 +31,36 @@ class FillBlanks extends Question
* function which redefines Question::createAnswersForm
* @param the formvalidator instance
*/
function createAnswersForm($form)
{
function createAnswersForm ($form) {
$fillBlanksAllowedSeparator = self::getAllowedSeparator();
$defaults = array();
if (!empty($this->id)) {
$objAnswer = new answer($this->id);
// the question is encoded like this
// [A] B [C] D [E] F::10,10,10@1
// number 1 before the "@" means that is a switchable fill in blank question
// [A] B [C] D [E] F::10,10,10@ or [A] B [C] D [E] F::10,10,10
// means that is a normal fill blank question
$pre_array = explode('::', $objAnswer->selectAnswer(1));
//make sure we only take the last bit to find special marks
$sz = count($pre_array);
$is_set_switchable = explode('@', $pre_array[$sz-1]);
$objectAnswer = new answer($this->id);
$answer = $objectAnswer->selectAnswer(1);
$listAnswersInfo = FillBlanks::getAnswerInfo($answer);
if ($is_set_switchable[1]) {
if ($listAnswersInfo["switchable"]) {
$defaults['multiple_answer'] = 1;
} else {
$defaults['multiple_answer'] = 0;
}
//Take the complete string except after the last '::'
$defaults['answer'] = '';
for ($i=0; $i<($sz-1); $i++) {
$defaults['answer'] .= $pre_array[$i];
}
$a_weightings = explode(',', $is_set_switchable[0]);
//take the complete string except after the last '::'
$defaults['answer'] = $listAnswersInfo["text"];
$defaults['select_separator'] = $listAnswersInfo["blankseparatornumber"];
$blanksepartornumber = $listAnswersInfo["blankseparatornumber"];
} else {
$defaults['answer'] = get_lang('DefaultTextInBlanks');
$defaults['select_separator'] = 0;
$blanksepartornumber = 0;
}
$blankSeparatortStart = self::getStartSeparator($blanksepartornumber);
$blankSeparatortEnd = self::getEndSeparator($blanksepartornumber);
$blankSeparatortStartRegexp = self::escapeForRegexp($blankSeparatortStart);
$blankSeparatortEndRegexp = self::escapeForRegexp($blankSeparatortEnd);
$setValues = null;
if (isset($a_weightings) && count($a_weightings) > 0) {
@ -74,6 +72,11 @@ class FillBlanks extends Question
// javascript
echo '<script>
var blankSeparatortStart = "'.$blankSeparatortStart.'";
var blankSeparatortEnd = "'.$blankSeparatortEnd.'";
var blankSeparatortStartRegexp = getBlankSeparatorRegexp(blankSeparatortStart);
var blankSeparatortEndRegexp = getBlankSeparatorRegexp(blankSeparatortEnd);
function FCKeditor_OnComplete( editorInstance ) {
if (window.attachEvent) {
editorInstance.EditorDocument.attachEvent("onkeyup", updateBlanks) ;
@ -86,50 +89,186 @@ class FillBlanks extends Question
function updateBlanks() {
if (firstTime) {
field = document.getElementById("answer");
var field = document.getElementById("answer");
var answer = field.value;
} else {
var oEditor = FCKeditorAPI.GetInstance("answer");
//var answer = oEditor.GetXHTML(true);
var answer = oEditor.EditorDocument.body.innerHTML;
}
var blanks = answer.match(/\[[^\]]*\]/g);
var fields = "<div class=\"control-group\"><label class=\"control-label\">'.get_lang('Weighting').'</label><div class=\"controls\"><table>";
// disable the save button, if not blanks have been created
$("button").attr("disabled", "disabled");
$("#defineoneblank").show();
var blanksRegexp = "/"+blankSeparatortStartRegexp+"[^"+blankSeparatortStartRegexp+"]*"+blankSeparatortEndRegexp+"/g";
var blanks = answer.match(eval(blanksRegexp));
var fields = "<div class=\"control-group\">";
fields += "<label class=\"control-label\">'.get_lang('Weighting').'</label>";
fields += "<div class=\"controls\">";
fields += "<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>";
if (blanks != null) {
for (i=0 ; i<blanks.length ; i++){
if (document.getElementById("weighting["+i+"]"))
value = document.getElementById("weighting["+i+"]").value;
else
value = "10";
fields += "<tr><td><label>"+blanks[i]+"</label></td><td><input style=\"margin-left: 0em;\" size=\"5\" value=\""+value+"\" type=\"text\" id=\"weighting["+i+"]\" name=\"weighting["+i+"]\" /></td></tr>";
for (var i=0 ; i < blanks.length ; i++){
// remove forbidden characters that causes bugs
blanks[i] = removeForbiddenChars(blanks[i]);
// trim blanks between brackets
blanks[i] = trimBlanksBetweenSeparator(blanks[i], blankSeparatortStart, blankSeparatortEnd);
// if the word is empty []
if (blanks[i] == blankSeparatortStartRegexp+blankSeparatortEndRegexp) {
break;
}
// get input size
var lainputsize = 200;
if ($("#samplesize\\\["+i+"\\\]").width()) {
lainputsize = $("#samplesize\\\["+i+"\\\]").width();
}
if (document.getElementById("weighting["+i+"]")) {
var value = document.getElementById("weighting["+i+"]").value;
} else {
var value = "10";
}
fields += "<tr>";
fields += "<td>"+blanks[i]+"</td>";
fields += "<td><input style=\"width:20px\" value=\""+value+"\" type=\"text\" id=\"weighting["+i+"]\" name=\"weighting["+i+"]\" /></td>";
fields += "<td>";
fields += "<input type=\"button\" value=\"-\" onclick=\"changeInputSize(-1, "+i+")\">";
fields += "<input type=\"button\" value=\"+\" onclick=\"changeInputSize(1, "+i+")\">";
fields += "<input value=\""+blanks[i].substr(1, blanks[i].length - 2)+"\" style=\"width:"+lainputsize+"px\" disabled=disabled id=\"samplesize["+i+"]\"/>";
fields += "<input type=\"hidden\" id=\"sizeofinput["+i+"]\" name=\"sizeofinput["+i+"]\" value=\""+lainputsize+"\" \"/>";
fields += "</td>";
fields += "</tr>";
// enable the save button
$("button").removeAttr("disabled");
$("#defineoneblank").hide();
}
}
document.getElementById("blanks_weighting").innerHTML = fields + "</table></div></div>";
if (firstTime) {
firstTime = false;
'.$setValues.'
';
if (count($listAnswersInfo["tabweighting"]) > 0) {
foreach ($listAnswersInfo["tabweighting"] as $i => $weighting) {
echo 'document.getElementById("weighting['.$i.']").value = "'.$weighting.'";';
}
foreach ($listAnswersInfo["tabinputsize"] as $i => $sizeOfInput) {
echo 'document.getElementById("sizeofinput['.$i.']").value = "'.$sizeOfInput.'";';
echo '$("#samplesize\\\['.$i.'\\\]").width('.$sizeOfInput.');';
}
}
echo '}
';
echo '
}
window.onload = updateBlanks;
function getInputSize() {
var outTabSize = new Array();
$("input").each(function() {
if ($(this).attr("id") && $(this).attr("id").match(/samplesize/)) {
var tabidnum = $(this).attr("id").match(/\d+/);
var idnum = tabidnum[0];
var thewidth = $(this).next().attr("value");
tabInputSize[idnum] = thewidth;
}
});
}
function changeInputSize(inCoef, inIdNum)
{
var currentWidth = $("#samplesize\\\["+inIdNum+"\\\]").width();
var newWidth = currentWidth + inCoef * 20;
newWidth = Math.max(20, newWidth);
newWidth = Math.min(newWidth, 600);
$("#samplesize\\\["+inIdNum+"\\\]").width(newWidth);
$("#sizeofinput\\\["+inIdNum+"\\\]").attr("value", newWidth);
}
function removeForbiddenChars(inTxt) {
outTxt = inTxt;
outTxt = outTxt.replace(/&quot;/g, ""); // remove the char
outTxt = outTxt.replace(/\x22/g, ""); // remove the char
outTxt = outTxt.replace(/"/g, ""); // remove the char
outTxt = outTxt.replace(/\\\\/g, ""); // remove the \ char
outTxt = outTxt.replace(/&nbsp;/g, " ");
outTxt = outTxt.replace(/^ +/, "");
outTxt = outTxt.replace(/ +$/, "");
return outTxt;
}
function changeBlankSeparator()
{
var separatorNumber = $("#select_separator").val();
var tabSeparator = getSeparatorFromNumber(separatorNumber);
blankSeparatortStart = tabSeparator[0];
blankSeparatortEnd = tabSeparator[1];
blankSeparatortStartRegexp = getBlankSeparatorRegexp(blankSeparatortStart);
blankSeparatortEndRegexp = getBlankSeparatorRegexp(blankSeparatortEnd);
updateBlanks();
}
// this function is the same than the PHP one
// if modify it modify the php one escapeForRegexp
function getBlankSeparatorRegexp(inTxt)
{
var tabSpecialChar = new Array(".", "+", "*", "?", "[", "^", "]", "$", "(", ")",
"{", "}", "=", "!", "<", ">", "|", ":", "-", ")");
for (var i=0; i < tabSpecialChar.length; i++) {
if (inTxt == tabSpecialChar[i]) {
return "\\\"+inTxt;
}
}
return inTxt;
}
// this function is the same than the PHP one
// if modify it modify the php one getAllowedSeparator
function getSeparatorFromNumber(innumber)
{
tabSeparator = new Array();
tabSeparator[0] = new Array("[", "]");
tabSeparator[1] = new Array("{", "}");
tabSeparator[2] = new Array("(", ")");
tabSeparator[3] = new Array("*", "*");
tabSeparator[4] = new Array("#", "#");
tabSeparator[5] = new Array("%", "%");
tabSeparator[6] = new Array("$", "$");
return tabSeparator[innumber];
}
function trimBlanksBetweenSeparator(inTxt, inSeparatorStart, inSeparatorEnd)
{
// blankSeparatortStartRegexp
// blankSeparatortEndRegexp
var result = inTxt
result = result.replace(inSeparatorStart, "");
result = result.replace(inSeparatorEnd, "");
result = result.trim();
return inSeparatorStart+result+inSeparatorEnd;
}
</script>';
// answer
$form->addElement ('label', null, '<br /><br />'.get_lang('TypeTextBelow').', '.get_lang('And').' '.get_lang('UseTagForBlank'));
$form->addElement ('html_editor', 'answer', '<img src="../img/fill_field.png">','id="answer" cols="122" rows="6" onkeyup="javascript: updateBlanks(this);"', array('ToolbarSet' => 'TestQuestionDescription', 'Width' => '100%', 'Height' => '350'));
$form -> addRule ('answer',get_lang('GiveText'),'required');
$form->addRule('answer', get_lang('DefineBlanks'),'regex','/\[.*\]/');
//added multiple answers
$form->addElement ('checkbox','multiple_answer','', get_lang('FillInBlankSwitchable'));
$form->addElement('select', 'select_separator', get_lang("SelectFillTheBlankSeparator"), self::getAllowedSeparatorForSelect(), ' id="select_separator" style="width:150px" onchange="changeBlankSeparator()" ');
$form->addElement ('label', null, '<input type="button" onclick="updateBlanks()" value="'.get_lang('RefreshBlanks').'" class="btn" />');
$form->addElement('html','<div id="blanks_weighting"></div>');
global $text, $class;
// setting the save button here and not in the question class.php
$form->addElement('html','<div id="defineoneblank" style="color:#D04A66; margin-left:160px">'.get_lang('DefineBlanks').'</div>');
$form->addElement('style_submit_button','submitQuestion',$text, 'class="'.$class.'"');
if (!empty($this -> id)) {
@ -148,37 +287,109 @@ class FillBlanks extends Question
function processAnswersCreation($form)
{
global $charset;
$answer = $form->getSubmitValue('answer');
// Due the fckeditor transform the elements to their HTML value
$answer = api_html_entity_decode($answer, ENT_QUOTES, $charset);
// remove the :: eventually written by the user
$answer = str_replace('::','',$answer);
// remove starting and ending space and &nbsp;
$answer = api_preg_replace("/\xc2\xa0/", " ", $answer);
// start and end separator
$blankStartSeparator = self::getStartSeparator($form->getSubmitValue('select_separator'));
$blankEndSeparator = self::getEndSeparator($form->getSubmitValue('select_separator'));
$blankStartSeparatorRegexp = self::escapeForRegexp($blankStartSeparator);
$blankEndSeparatorRegexp = self::escapeForRegexp($blankEndSeparator);
// remove spaces at the beginning and the end of text in square brackets
$answer = preg_replace_callback("/".$blankStartSeparatorRegexp."[^]]+".$blankEndSeparatorRegexp."/",
function ($matches) use ($blankStartSeparator, $blankEndSeparator) {
$matchingResult = $matches[0];
$matchingResult = trim($matchingResult, $blankStartSeparator);
$matchingResult = trim($matchingResult, $blankEndSeparator);
$matchingResult = trim($matchingResult);
// remove forbidden chars
$matchingResult = str_replace("/\\/", "", $matchingResult);
$matchingResult = str_replace('/"/', "", $matchingResult);
return $blankStartSeparator.$matchingResult.$blankEndSeparator;
},
$answer);
// get the blanks weightings
$nb = preg_match_all('/\[[^\]]*\]/', $answer, $blanks);
if (isset($_GET['editQuestion'])) {
$nb = preg_match_all('/'.$blankStartSeparatorRegexp.'[^'.$blankStartSeparatorRegexp.']*'.$blankEndSeparatorRegexp.'/', $answer, $blanks);
if(isset($_GET['editQuestion']))
{
$this -> weighting = 0;
}
/* if we have some [tobefound] in the text
build the string to save the following in the answers table
<p>I use a [computer] and a [pen].</p>
becomes
<p>I use a [computer] and a [pen].</p>::100,50:100,50@1
++++++++-------**
--- -- --- -- -
A B (C) (D)(E)
+++++++ : required, weighting of each words
------- : optional, input width to display, 200 if not present
** : equal @1 if "Allow answers order switches" has been checked, @ otherwise
A : weighting for the word [computer]
B : weighting for the word [pen]
C : input width for the word [computer]
D : input width for the word [pen]
E : equal @1 if "Allow answers order switches" has been checked, @ otherwise
*/
if($nb > 0) {
$answer .= '::';
// weighting
for($i=0 ; $i < $nb ; ++$i) {
$blankItem = $blanks[0][$i];
$replace = array("[", "]");
$newBlankItem = str_replace($replace, "", $blankItem);
$newBlankItem = "[".trim($newBlankItem)."]";
$answer = str_replace($blankItem, $newBlankItem, $answer);
$answer .= $form->getSubmitValue('weighting['.$i.']').',';
// enter the weighting of word $i
$answer .= $form->getSubmitValue('weighting['.$i.']');
// not the last word, add ","
if ($i != $nb - 1) {
$answer .= ",";
}
// calculate the global weightning for the question
$this -> weighting += $form->getSubmitValue('weighting['.$i.']');
}
$answer = api_substr($answer, 0, -1);
// input width
$answer .= ":";
for ($i=0 ; $i < $nb ; ++$i) {
// enter the width of input for word $i
$answer .= $form->getSubmitValue('sizeofinput['.$i.']');
// not the last word, add ","
if ($i != $nb - 1) {
$answer .= ",";
}
}
}
// write the blank separator code number
// see function getAllowedSeparator
/*
0 [...]
1 {...}
2 (...)
3 *...*
4 #...#
5 %...%
6 $...$
*/
$answer .= ":".$form->getSubmitValue('select_separator');
// Allow answers order switches
$is_multiple = $form -> getSubmitValue('multiple_answer');
$answer.='@'.$is_multiple;
$this -> save();
$objAnswer = new answer($this->id);
$objAnswer->createAnswer($answer, 0, '', 0, '1');
$objAnswer->createAnswer($answer, 0, '', 0, 1);
$objAnswer->save();
}
@ -197,4 +408,496 @@ class FillBlanks extends Question
</tr>';
return $header;
}
/**
* @param $separatorStartRegexp
* @param $separatorEndRegexp
* @param $correctItemRegexp
* @param $questionId
* @param $correctItem
* @param $attributes
* @param $answer
* @param $listAnswersInfo
* @param $displayForStudent
* @return string
*/
public static function getFillTheBlankHtml($separatorStartRegexp, $separatorEndRegexp, $correctItemRegexp, $questionId, $correctItem, $attributes, $answer, $listAnswersInfo, $displayForStudent, $inBlankNumber)
{
$result = "";
$inTabTeacherSolution = $listAnswersInfo['tabwords'];
$inTeacherSolution = $inTabTeacherSolution[$inBlankNumber];
switch (self::getFillTheBlankAnswerType($inTeacherSolution)) {
case self::FILL_THE_BLANK_MENU:
$selected = "";
// the blank menu
$optionMenu = "";
// display a menu from answer separated with |
// if display for student, shuffle the correct answer menu
$listMenu = self::getFillTheBlankMenuAnswers($inTeacherSolution, $displayForStudent);
$result .= '<select name="choice['.$questionId.'][]">';
for ($k=0; $k < count($listMenu); $k++) {
$selected = "";
if ($correctItem == $listMenu[$k]) {
$selected = " selected=selected ";
}
// if in teacher view, display the first item by default, which is the right answer
if ($k==0 && !$displayForStudent) {
$selected = " selected=selected ";
}
$optionMenu .= '<option '.$selected.' value="'.$listMenu[$k].'">'.$listMenu[$k].'</option>';
}
if ($selected == "") {
// no good answer have been found...
$selected = " selected=selected ";
}
$result .= "<option $selected value=''>--</option>";
$result .= $optionMenu;
$result .= '</select>';
break;
case self::FILL_THE_BLANK_SEVERAL_ANSWER:
case self::FILL_THE_BLANK_STANDARD:
default:
$result = Display::input('text', "choice[$questionId][]", $correctItem, $attributes);
break;
}
return $result;
}
/**
* Return an array with the differents choice avaliable when the bracket is a menu
* @param $correctAnswer
* @param $displayForStudent true if we want to shuffle the choices of the menu for students
* @return array
*/
public static function getFillTheBlankMenuAnswers($correctAnswer, $displayForStudent)
{
// if $inDisplayForStudent, then shuffle the result array
$listChoises = api_preg_split("/\|/", $correctAnswer);
if ($displayForStudent) {
shuffle($listChoises);
}
return $listChoises;
}
/**
* Return the array indice of the student answer
* @param $correctAnswer the menu Choice1|Choice2|Choice3
* @param $studentAnswer the student answer must be Choice1 or Choice2 or Choice3
* @return int in the exemple 0 1 or 2 depending of the choice of the student
*/
public static function getFillTheBlankMenuAnswerNum($correctAnswer, $studentAnswer)
{
$listChoices = self::getFillTheBlankMenuAnswers($correctAnswer, false);
foreach ($listChoices as $num => $value) {
if ($value == $studentAnswer) {
return $num;
}
}
return -1; // should not happened, because student choose the answer in a menu of possible answers
}
/**
* return the possible answer if bracket is a multiple choice menu
* @param $correctAnswer
* @return array
*/
public static function getFillTheBlankSeveralAnswers($correctAnswer)
{
// is answer||Answer||response||Response , mean answer or Answer ...
$listSeveral = api_preg_split("/\|\|/", $correctAnswer);
return $listSeveral;
}
/**
* Return true if student answer is right according to the correctAnswer
* it is not so simple as equality, because of the type of Fill The Blank question
* eg : studentNaswer = 'Un' and correctAnswer = 'Un||1||un'
* @param $studentAnswer the [studentanswer] of the info array of the answer field
* @param $correctAnswer the [tabwords] of the info array of the answer field
* @return bool
*/
public static function isGoodStudentAnswer($studentAnswer, $correctAnswer)
{
switch (self::getFillTheBlankAnswerType($correctAnswer)) {
case self::FILL_THE_BLANK_MENU:
$listMenu = self::getFillTheBlankMenuAnswers($correctAnswer, false);
return ($listMenu[0] == $studentAnswer);
break;
case self::FILL_THE_BLANK_SEVERAL_ANSWER:
// the answer must be one of the choice made
$listSeveral = self::getFillTheBlankSeveralAnswers($correctAnswer);
return (in_array($studentAnswer, $listSeveral));
break;
case self::FILL_THE_BLANK_STANDARD:
default:
return ($studentAnswer == $correctAnswer);
}
}
public static function getFillTheBlankAnswerType($correctAnswer)
{
if (api_strpos($correctAnswer, "|") && !api_strpos($correctAnswer, "||")) {
return self::FILL_THE_BLANK_MENU;
} elseif (api_strpos($correctAnswer, "||")) {
return self::FILL_THE_BLANK_SEVERAL_ANSWER;
} else {
return self::FILL_THE_BLANK_STANDARD;
}
}
/**
* Return information about the answer
* @param string $answer : the text of the answer of the question
* @param bool $inIsStudentAnswer : true if it is a student answer and not the empty question model
* @return array of information about the answer
*/
public static function getAnswerInfo($userAnswer = "", $isStudentAnswer = false)
{
$listAnswerResults = array();
$listAnswerResults['text'] = "";
$listAnswerResults['wordsCount'] = 0;
$listAnswerResults['tabwordsbracket'] = array();
$listAnswerResults['tabwords'] = array();
$listAnswerResults['tabweighting'] = array();
$listAnswerResults['tabinputsize'] = array();
$listAnswerResults['switchable'] = "";
$listAnswerResults['studentanswer'] = array();
$listAnswerResults['studentscore'] = array();
$listAnswerResults['blankseparatornumber'] = 0;
api_preg_match("/(.*)::(.*)$/s", $userAnswer, $listResult);
if (count($listResult) < 2) {
$listDoubleColon[] = $listResult;
$listDoubleColon[] = "";
} else {
$listDoubleColon[] = $listResult[1];
$listDoubleColon[] = $listResult[2];
}
$listAnswerResults['systemstring'] = $listDoubleColon[1];
//make sure we only take the last bit to find special marks
$listArobaseSplit = explode('@', $listDoubleColon[1]);
if (count($listArobaseSplit) < 2) {
$listArobaseSplit[1] = "";
}
//take the complete string except after the last '::'
$listDetails = explode(":", $listArobaseSplit[0]);
// < number of item after the ::[score]:[size]:[separator_id]@ , here there are 3
if (count($listDetails) < 3) {
$listWeightings = explode(',', $listDetails[0]);
$listSizeOfInput = array();
for ($i=0; $i < count($listWeightings); $i++) {
$listSizeOfInput[] = 200;
}
$blankSeparatorNumber = 0; // 0 is [...]
} else {
$listWeightings = explode(',', $listDetails[0]);
$listSizeOfInput = explode(',', $listDetails[1]);
$blankSeparatorNumber = $listDetails[2];
}
$listAnswerResults['text'] = $listDoubleColon[0];
$listAnswerResults['tabweighting'] = $listWeightings;
$listAnswerResults['tabinputsize'] = $listSizeOfInput;
$listAnswerResults['switchable'] = $listArobaseSplit[1];
$listAnswerResults['blankseparatorstart'] = self::getStartSeparator($blankSeparatorNumber);
$listAnswerResults['blankseparatorend'] = self::getEndSeparator($blankSeparatorNumber);
$listAnswerResults['blankseparatornumber'] = $blankSeparatorNumber;
$blankCharStart = self::getStartSeparator($blankSeparatorNumber);
$blankCharEnd = self::getEndSeparator($blankSeparatorNumber);
$blankCharStartForRegexp = self::escapeForRegexp($blankCharStart);
$blankCharEndForRegexp = self::escapeForRegexp($blankCharEnd);
// get all blanks words
$listAnswerResults['wordsCount'] = preg_match_all('/'.$blankCharStartForRegexp.'[^'.$blankCharEndForRegexp.']*'.$blankCharEndForRegexp.'/', $listDoubleColon[0], $listWords);
if ($listAnswerResults['wordsCount'] > 0) {
$listAnswerResults['tabwordsbracket'] = $listWords[0];
// remove [ and ] in string
array_walk($listWords[0],function (&$value, $key, $tabBlankChar)
{
$trimChars = "";
for ($i=0; $i < count($tabBlankChar); $i++) {
$trimChars .= $tabBlankChar[$i];
}
$value = trim($value, $trimChars);
},
array($blankCharStart, $blankCharEnd)
);
$listAnswerResults['tabwords'] = $listWords[0];
}
// get all common words
$commonWords = preg_replace('/'.$blankCharStartForRegexp.'[^'.$blankCharEndForRegexp.']*'.$blankCharEndForRegexp.'/', "::", $listDoubleColon[0]);
// if student answer, the second [] is the student answer, the third is if student scored or not
$listBrackets = array();
$listWords = array();
if ($isStudentAnswer) {
for ($i=0; $i < count($listAnswerResults['tabwords']); $i++) {
$listBrackets[] = $listAnswerResults['tabwordsbracket'][$i];
$listWords[] = $listAnswerResults['tabwords'][$i];
if ($i+1 < count($listAnswerResults['tabwords'])) { // should always be
$i++;
}
$listAnswerResults['studentanswer'][] = $listAnswerResults['tabwords'][$i];
if ($i+1 < count($listAnswerResults['tabwords'])) { // should always be
$i++;
}
$listAnswerResults['studentscore'][] = $listAnswerResults['tabwords'][$i];
}
$listAnswerResults['tabwords'] = $listWords;
$listAnswerResults['tabwordsbracket'] = $listBrackets;
// if we are in student view, we've got 3 times :::::: for common words
$commonWords = preg_replace("/::::::/", "::", $commonWords);
}
$listAnswerResults['commonwords'] = explode("::", $commonWords);
return $listAnswerResults;
}
/**
* Replace the occurence of blank word with [correct answer][student answer][answer is correct]
* @param array $listWithStudentAnswer
* @return string
*/
public static function getAnswerInStudentAttempt($listWithStudentAnswer)
{
$separatorStart = $listWithStudentAnswer['blankseparatorstart'];
$separatorEnd = $listWithStudentAnswer['blankseparatorend'];
// lets rebuild the sentence with [correct answer][student answer][answer is correct]
$result = "";
for ($i=0; $i < count($listWithStudentAnswer['commonwords']) - 1; $i++) {
$result .= $listWithStudentAnswer['commonwords'][$i];
$result .= $listWithStudentAnswer['tabwordsbracket'][$i];
$result .= $separatorStart.$listWithStudentAnswer['studentanswer'][$i].$separatorEnd;
$result .= $separatorStart.$listWithStudentAnswer['studentscore'][$i].$separatorEnd;
}
$result .= $listWithStudentAnswer['commonwords'][$i];
$result .= "::";
// add the system string
$result .= $listWithStudentAnswer['systemstring'];
return $result;
}
/**
* This function is the same than the js one above getBlankSeparatorRegexp
* @param $inChar
* @return string
*/
public static function escapeForRegexp($inChar)
{
if (in_array($inChar, array(".", "+", "*", "?", "[", "^", "]", "$", "(", ")", "{", "}", "=", "!", ">", "|", ":", "-", ")"))) {
return "\\".$inChar;
} else {
return $inChar;
}
}
/**
* return $text protected for use in regexp
* @param $text
* @return mixed
*/
public static function getRegexpProtected($text)
{
$listRegexpCharacters = array("/", ".", "+", "*", "?", "[", "^", "]", "$", "(", ")", "{", "}", "=", "!", ">", "|", ":", "-", ")");
$result = $text;
for ($i=0; $i < count($listRegexpCharacters); $i++) {
$result = str_replace($listRegexpCharacters[$i], "\\".$listRegexpCharacters[$i], $result);
}
return $result;
}
/**
* This function must be the same than the js one getSeparatorFromNumber above
* @return array
*/
public static function getAllowedSeparator()
{
$fillBlanksAllowedSeparator = array(
array('[', ']'),
array('{', '}'),
array('(', ')'),
array('*', '*'),
array('#', '#'),
array('%', '%'),
array('$', '$'),
);
return $fillBlanksAllowedSeparator;
}
/**
* return the start separator for answer
* @param $number
* @return mixed
*/
public static function getStartSeparator($number)
{
$listSeparators = self::getAllowedSeparator();
return $listSeparators[$number][0];
}
/**
* return the end separator for answer
* @param $number
* @return mixed
*/
public static function getEndSeparator($number)
{
$listSeparators = self::getAllowedSeparator();
return $listSeparators[$number][1];
}
/**
* return as a desciption text, array of allowed separtors for question eg: array("[...]", "(...)")
* @return array
*/
public static function getAllowedSeparatorForSelect()
{
$listResults = array();
$fillBlanksAllowedSeparator = self::getAllowedSeparator();
for ($i=0; $i < count($fillBlanksAllowedSeparator); $i++) {
$listResults[] = $fillBlanksAllowedSeparator[$i][0]."...".$fillBlanksAllowedSeparator[$i][1];
}
return $listResults;
}
/**
* return the code number of the separator for the question
* @param $startSeparator
* @param $endSeparator
* @return int
*/
public function getDefaultSeparatorNumber($startSeparator, $endSeparator)
{
$listSeparators = self::getAllowedSeparator();
$result = 0;
for ($i=0; $i < count($listSeparators); $i++) {
if ($listSeparators[$i][0] == $startSeparator && $listSeparators[$i][1] == $endSeparator) {
$result = $i;
}
}
return $result;
}
/**
* return the HTML display of the answer
* @param $answer
* @return string
*/
public static function getHtmlDisplayForAsnwer($answer, $resultsDisabled = false)
{
$result = "";
$listStudentAnswerInfo = self::getAnswerInfo($answer, true);
// rebluid the answer with good HTML style
// this is the student answer, right or wrong
for ($i=0; $i < count($listStudentAnswerInfo['studentanswer']); $i++) {
if ($listStudentAnswerInfo['studentscore'][$i] == 1) {
$listStudentAnswerInfo['studentanswer'][$i] = self::getHtmlRightAsnwer($listStudentAnswerInfo['studentanswer'][$i], $listStudentAnswerInfo['tabwords'][$i], $resultsDisabled);
} else {
$listStudentAnswerInfo['studentanswer'][$i] = self::getHtmlWrongAnswer($listStudentAnswerInfo['studentanswer'][$i], $listStudentAnswerInfo['tabwords'][$i], $resultsDisabled);
}
}
// rebuild the sentence with student answer inserted
for ($i=0; $i < count($listStudentAnswerInfo['commonwords']); $i++) {
$result .= $listStudentAnswerInfo['commonwords'][$i];
$result .= $listStudentAnswerInfo['studentanswer'][$i];
}
// the last common word (should be </p>)
$result .= $listStudentAnswerInfo['commonwords'][$i];
return $result;
}
/**
* return the HTML code of answer for correct and wrong answer
* @param $answer
* @param $correct
* @param $right
* @return string
*/
public static function getHtmlAnswer($answer, $correct, $right, $resultsDisabled = false)
{
$style = "color: green";
if (!$right) {
$style = "color: red; text-decoration: line-through;";
}
$type = FillBlanks::getFillTheBlankAnswerType($correct);
switch ($type) {
case self::FILL_THE_BLANK_MENU:
$correctAnswerHtml = "";
$listPossibleAnswers = FillBlanks::getFillTheBlankMenuAnswers($correct, false);
$correctAnswerHtml .= "<span style='color: green'>".$listPossibleAnswers[0]."</span>";
$correctAnswerHtml .= " <span style='font-weight:normal'>(";
for ($i=1; $i < count($listPossibleAnswers); $i++) {
$correctAnswerHtml .= $listPossibleAnswers[$i];
if ($i != count($listPossibleAnswers) - 1) {
$correctAnswerHtml .= " | ";
}
}
$correctAnswerHtml .= ")</span>";
break;
case self::FILL_THE_BLANK_SEVERAL_ANSWER:
$listCorrects = explode("||", $correct);
$firstCorrect = $correct;
if (count($listCorrects) > 0) {
$firstCorrect = $listCorrects[0];
}
$correctAnswerHtml = "<span style='color: green'>".$firstCorrect."</span>";
break;
case self::FILL_THE_BLANK_STANDARD:
default:
$correctAnswerHtml = "<span style='color: green'>".$correct."</span>";
}
if ($resultsDisabled) {
$correctAnswerHtml = "<span title='".get_lang("ExerciseWithFeedbackWithoutCorrectionComment")."'> - </span>";
}
$result = "<span style='border:1px solid black; border-radius:5px; padding:2px; font-weight:bold;'>";
$result .= "<span style='$style'>".$answer."</span>";
$result .= "&nbsp;<span style='font-size:120%;'>/</span>&nbsp;";
$result .= $correctAnswerHtml;
$result .= "</span>";
return $result;
}
/**
* return HTML code for correct answer
* @param $answer
* @param $correct
* @return string
*/
public static function getHtmlRightAsnwer($answer, $correct, $resultsDisabled = false)
{
return self::getHtmlAnswer($answer, $correct, true, $resultsDisabled);
}
/**
* return HTML code for wrong answer
* @param $answer
* @param $correct
* @return string
*/
public static function getHtmlWrongAnswer($answer, $correct, $resultsDisabled = false)
{
return self::getHtmlAnswer($answer, $correct, false, $resultsDisabled);
}
}

@ -57,7 +57,8 @@ if (!empty($question_list)) {
$question_id,
$exercise_id,
$courseCode,
$sessionId
$sessionId,
$question_obj->type
);
$data[$question_id]['name'] = cut($question_obj->question, 100);

@ -19,26 +19,27 @@ class ExerciseShowFunctions
{
/**
* Shows the answer to a fill-in-the-blanks question, as HTML
* Display in the student result page, with score and comm
* @param string Answer text
* @param int Exercise ID
* @param int Question ID
* @return void
*/
static function display_fill_in_blanks_answer($feedback_type, $answer, $id, $questionId)
{
static function display_fill_in_blanks_answer($feedbackType, $answer, $id, $questionId, $inResultsDisabled) {
$answerHTML = FillBlanks::getHtmlDisplayForAsnwer($answer, $inResultsDisabled);
if (empty($id)) {
echo '<tr><td>'. (Security::remove_XSS($answer)).'</td></tr>';
echo '<tr><td>';
echo Security::remove_XSS($answerHTML, COURSEMANAGERLOWSECURITY);
echo '</td></tr>';
} else {
?>
<tr>
<td>
<?php
echo (Security::remove_XSS($answer));
?>
<?php echo nl2br(Security::remove_XSS($answerHTML, COURSEMANAGERLOWSECURITY)); ?>
</td>
<?php
if (!api_is_allowed_to_edit(null,true) && $feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM) { ?>
if (!api_is_allowed_to_edit(null,true) && $feedbackType != EXERCISE_FEEDBACK_TYPE_EXAM) { ?>
<td>
<?php
$comm = get_comments($id,$questionId);

Loading…
Cancel
Save