|
@@ -2599,85 +2599,253 @@ class Exercise
|
|
|
}
|
|
|
break;
|
|
|
case FILL_IN_BLANKS:
|
|
|
-
|
|
|
- // 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 data are choice[]
|
|
|
-
|
|
|
- $listCorrectAnswers = FillBlanks::getAnswerInfo($answer);
|
|
|
- $switchableAnswerSet = $listCorrectAnswers["switchable"];
|
|
|
- $answerWeighting = $listCorrectAnswers["tabweighting"];
|
|
|
- // user choices is an array $choice
|
|
|
-
|
|
|
- // get existing user data in n the BDD
|
|
|
+ $str = '';
|
|
|
if ($from_database) {
|
|
|
$sql = "SELECT answer
|
|
|
- FROM $TBL_TRACK_ATTEMPT
|
|
|
- WHERE
|
|
|
- exe_id = $exeId AND
|
|
|
- question_id= ".intval($questionId);
|
|
|
+ FROM $TBL_TRACK_ATTEMPT
|
|
|
+ WHERE
|
|
|
+ exe_id = $exeId AND
|
|
|
+ question_id= ".intval($questionId);
|
|
|
$result = Database::query($sql);
|
|
|
$str = Database::result($result, 0, 'answer');
|
|
|
-
|
|
|
- $listStudentResults = FillBlanks::getAnswerInfo($str, true);
|
|
|
- $choice = $listStudentResults['studentanswer'];
|
|
|
}
|
|
|
|
|
|
- // 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 = isset($choice[$i]) ? trim($choice[$i]) : '';
|
|
|
+ if ($saved_results == false && strpos($str, 'font color') !== false) {
|
|
|
+ // 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]);
|
|
|
+ // 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;
|
|
|
+ }
|
|
|
+ if ($from_database) {
|
|
|
+ $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);
|
|
|
+ }
|
|
|
+ $answer = '';
|
|
|
+ $real_correct_tags = $correct_tags;
|
|
|
+ $chosen_list = array();
|
|
|
|
|
|
- // 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
|
|
|
- if (!$from_database) {
|
|
|
- $studentAnswer = htmlentities(
|
|
|
- api_utf8_encode($studentAnswer)
|
|
|
- );
|
|
|
+ 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]) {
|
|
|
+ // 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 that causes issue
|
|
|
+ }
|
|
|
+ } 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
|
|
|
+ $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 that causes issue
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- $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];
|
|
|
- $isAnswerCorrect = 1;
|
|
|
+ // 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;
|
|
|
- $listCorrectAnswers['studentscore'][$i] = $isAnswerCorrect;
|
|
|
}
|
|
|
} else {
|
|
|
- // switchable answer
|
|
|
- $listStudentAnswerTemp = $choice;
|
|
|
- $listTeacherAnswerTemp = $listCorrectAnswers['tabwords'];
|
|
|
- // for every teacher answer, check if there is a student answer
|
|
|
- for ($i=0; $i < count($listStudentAnswerTemp); $i++) {
|
|
|
- $studentAnswer = trim($listStudentAnswerTemp[$i]);
|
|
|
- $found = false;
|
|
|
- for ($j=0; $j < count($listTeacherAnswerTemp); $j++) {
|
|
|
- $correctAnswer = $listTeacherAnswerTemp[$j];
|
|
|
- if (!$found) {
|
|
|
- if (FillBlanks::isGoodStudentAnswer($studentAnswer, $correctAnswer)) {
|
|
|
- $questionScore += $answerWeighting[$i];
|
|
|
- $totalScore += $answerWeighting[$i];
|
|
|
- $listTeacherAnswerTemp[$j] = "";
|
|
|
- $found = true;
|
|
|
- }
|
|
|
+ // 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 data are choice[]
|
|
|
+ $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) {
|
|
|
+ $sql = "SELECT answer
|
|
|
+ FROM $TBL_TRACK_ATTEMPT
|
|
|
+ WHERE
|
|
|
+ exe_id = $exeId AND
|
|
|
+ question_id= ".intval($questionId);
|
|
|
+ $result = Database::query($sql);
|
|
|
+ $str = Database::result($result, 0, 'answer');
|
|
|
+ $listStudentResults = FillBlanks::getAnswerInfo(
|
|
|
+ $str,
|
|
|
+ true
|
|
|
+ );
|
|
|
+ $choice = $listStudentResults['studentanswer'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 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 = isset($choice[$i]) ? trim(
|
|
|
+ $choice[$i]
|
|
|
+ ) : '';
|
|
|
+
|
|
|
+ // 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
|
|
|
+ if (!$from_database) {
|
|
|
+ $studentAnswer = htmlentities(
|
|
|
+ api_utf8_encode($studentAnswer)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ $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];
|
|
|
+ $isAnswerCorrect = 1;
|
|
|
}
|
|
|
+ $listCorrectAnswers['studentanswer'][$i] = $studentAnswer;
|
|
|
+ $listCorrectAnswers['studentscore'][$i] = $isAnswerCorrect;
|
|
|
}
|
|
|
- $listCorrectAnswers['studentanswer'][$i] = $studentAnswer;
|
|
|
- if (!$found) {
|
|
|
- $listCorrectAnswers['studentscore'][$i] = 0;
|
|
|
- } else {
|
|
|
- $listCorrectAnswers['studentscore'][$i] = 1;
|
|
|
+ } else {
|
|
|
+ // switchable answer
|
|
|
+ $listStudentAnswerTemp = $choice;
|
|
|
+ $listTeacherAnswerTemp = $listCorrectAnswers['tabwords'];
|
|
|
+ // for every teacher answer, check if there is a student answer
|
|
|
+ for ($i = 0; $i < count(
|
|
|
+ $listStudentAnswerTemp
|
|
|
+ ); $i++) {
|
|
|
+ $studentAnswer = trim(
|
|
|
+ $listStudentAnswerTemp[$i]
|
|
|
+ );
|
|
|
+ $found = false;
|
|
|
+ for ($j = 0; $j < count(
|
|
|
+ $listTeacherAnswerTemp
|
|
|
+ ); $j++) {
|
|
|
+ $correctAnswer = $listTeacherAnswerTemp[$j];
|
|
|
+ if (!$found) {
|
|
|
+ if (FillBlanks::isGoodStudentAnswer(
|
|
|
+ $studentAnswer,
|
|
|
+ $correctAnswer
|
|
|
+ )
|
|
|
+ ) {
|
|
|
+ $questionScore += $answerWeighting[$i];
|
|
|
+ $totalScore += $answerWeighting[$i];
|
|
|
+ $listTeacherAnswerTemp[$j] = "";
|
|
|
+ $found = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $listCorrectAnswers['studentanswer'][$i] = $studentAnswer;
|
|
|
+ if (!$found) {
|
|
|
+ $listCorrectAnswers['studentscore'][$i] = 0;
|
|
|
+ } else {
|
|
|
+ $listCorrectAnswers['studentscore'][$i] = 1;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ $answer = FillBlanks::getAnswerInStudentAttempt(
|
|
|
+ $listCorrectAnswers
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
- $answer = FillBlanks::getAnswerInStudentAttempt($listCorrectAnswers);
|
|
|
break;
|
|
|
// for calculated answer
|
|
|
case CALCULATED_ANSWER:
|
|
@@ -3426,7 +3594,8 @@ class Exercise
|
|
|
$answer,
|
|
|
$exeId,
|
|
|
$questionId,
|
|
|
- $results_disabled
|
|
|
+ $results_disabled,
|
|
|
+ $str
|
|
|
);
|
|
|
break;
|
|
|
case CALCULATED_ANSWER:
|