Sfoglia il codice sorgente

Fix fill in blanks from 1.11.x see BT#3969

jmontoyaa 7 anni fa
parent
commit
24da1a49b3
2 ha cambiato i file con 232 aggiunte e 146 eliminazioni
  1. 104 59
      main/exercise/exercise.class.php
  2. 128 87
      main/exercise/fill_blanks.class.php

+ 104 - 59
main/exercise/exercise.class.php

@@ -17,6 +17,7 @@ use Chamilo\CourseBundle\Entity\CQuizCategory;
  */
 class Exercise
 {
+    public $iId;
     public $id;
     public $name;
     public $title;
@@ -49,7 +50,7 @@ class Exercise
     public $edit_exercise_in_lp = false;
     public $is_gradebook_locked = false;
     public $exercise_was_added_in_lp = false;
-    public $lpList = array();
+    public $lpList = [];
     public $force_edit_exercise_in_lp = false;
     public $categories;
     public $categories_grouping = true;
@@ -87,6 +88,7 @@ class Exercise
      */
     public function __construct($courseId = 0)
     {
+        $this->iId = 0;
         $this->id = 0;
         $this->exercise = '';
         $this->description = '';
@@ -95,7 +97,7 @@ class Exercise
         $this->random = 0;
         $this->random_answers = 0;
         $this->active = 1;
-        $this->questionList = array();
+        $this->questionList = [];
         $this->timeLimit = 0;
         $this->end_time = '';
         $this->start_time = '';
@@ -113,6 +115,7 @@ class Exercise
         $this->endButton = 0;
         $this->scoreTypeModel = 0;
         $this->globalCategoryId = null;
+        $this->notifications = [];
 
         if (!empty($courseId)) {
             $course_info = api_get_course_info_by_id($courseId);
@@ -152,6 +155,7 @@ class Exercise
 
         // if the exercise has been found
         if ($object = Database::fetch_object($result)) {
+            $this->iId = $object->iid;
             $this->id = $id;
             $this->exercise = $object->title;
             $this->name = $object->title;
@@ -229,14 +233,16 @@ class Exercise
             //overload questions list with recorded questions list
             //load questions only for exercises of type 'one question per page'
             //this is needed only is there is no questions
-            /*
-			// @todo not sure were in the code this is used somebody mess with the exercise tool
-			// @todo don't know who add that config and why $_configuration['live_exercise_tracking']
-			global $_configuration, $questionList;
-			if ($this->type == ONE_PER_PAGE && $_SERVER['REQUEST_METHOD'] != 'POST' && defined('QUESTION_LIST_ALREADY_LOGGED') &&
-			isset($_configuration['live_exercise_tracking']) && $_configuration['live_exercise_tracking']) {
-				$this->questionList = $questionList;
-			}*/
+
+            // @todo not sure were in the code this is used somebody mess with the exercise tool
+            // @todo don't know who add that config and why $_configuration['live_exercise_tracking']
+            /*global $_configuration, $questionList;
+            if ($this->type == ONE_PER_PAGE && $_SERVER['REQUEST_METHOD'] != 'POST'
+                && defined('QUESTION_LIST_ALREADY_LOGGED') &&
+                isset($_configuration['live_exercise_tracking']) && $_configuration['live_exercise_tracking']
+            ) {
+                $this->questionList = $questionList;
+            }*/
             return true;
         }
 
@@ -458,11 +464,11 @@ class Exercise
     {
         if (in_array(
             $random,
-            array(
+            [
                 EXERCISE_CATEGORY_RANDOM_SHUFFLED,
                 EXERCISE_CATEGORY_RANDOM_ORDERED,
                 EXERCISE_CATEGORY_RANDOM_DISABLED,
-            )
+            ]
         )) {
             $this->randomByCat = $random;
         } else {
@@ -604,8 +610,8 @@ class Exercise
         $limit,
         $sidx,
         $sord,
-        $whereCondition = array(),
-        $extraFields = array()
+        $whereCondition = [],
+        $extraFields = []
     ) {
         if (!empty($this->id)) {
             $category_list = TestCategory::getListOfCategoriesNameForTest(
@@ -625,7 +631,7 @@ class Exercise
 
             if (!empty($sidx) && !empty($sord)) {
                 if ($sidx == 'question') {
-                    if (in_array(strtolower($sord), array('desc', 'asc'))) {
+                    if (in_array(strtolower($sord), ['desc', 'asc'])) {
                         $orderCondition = " ORDER BY q.$sidx $sord";
                     }
                 }
@@ -640,7 +646,7 @@ class Exercise
             }
             $sql .= $limitCondition;
             $result = Database::query($sql);
-            $questions = array();
+            $questions = [];
             if (Database::num_rows($result)) {
                 if (!empty($extraFields)) {
                     $extraFieldValue = new ExtraFieldValue('question');
@@ -731,20 +737,20 @@ class Exercise
      */
     public function getQuestionOrderedListByName()
     {
-        $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
-        $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
+        $exerciseQuestionTable = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
+        $questionTable = Database::get_course_table(TABLE_QUIZ_QUESTION);
 
         // Getting question list from the order (question list drag n drop interface ).
         $sql = "SELECT e.question_id
-                FROM $TBL_EXERCICE_QUESTION e 
-                INNER JOIN $TBL_QUESTIONS q
+                FROM $exerciseQuestionTable e 
+                INNER JOIN $questionTable q
                 ON (e.question_id= q.id AND e.c_id = q.c_id)
                 WHERE 
                     e.c_id = {$this->course_id} AND 
                     e.exercice_id = '".$this->id."'
                 ORDER BY q.question";
         $result = Database::query($sql);
-        $list = array();
+        $list = [];
         if (Database::num_rows($result)) {
             $list = Database::store_result($result, 'ASSOC');
         }
@@ -757,7 +763,7 @@ class Exercise
      */
     private function getQuestionOrderedList()
     {
-        $questionList = array();
+        $questionList = [];
         $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
         $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
 
@@ -788,7 +794,7 @@ class Exercise
 
         // Fills the array with the question ID for this exercise
         // the key of the array is the question position
-        $temp_question_list = array();
+        $temp_question_list = [];
         $counter = 1;
         while ($new_object = Database::fetch_object($result)) {
             // Correct order.
@@ -901,10 +907,10 @@ class Exercise
         $question_list,
         $questionSelectionType
     ) {
-        $result = array(
-            'question_list' => array(),
-            'category_with_questions_list' => array()
-        );
+        $result = [
+            'question_list' => [],
+            'category_with_questions_list' => [],
+        ];
 
         // Order/random categories
         $cat = new TestCategory();
@@ -1707,11 +1713,14 @@ class Exercise
             $allow = api_get_configuration_value('allow_notification_setting_per_exercise');
             if ($allow === true) {
                 $notifications = $this->getNotifications();
-                $notifications = implode(',', $notifications);
-                $params['notifications'] = $notifications;
+                $params['notifications'] = '';
+                if (!empty($notifications)) {
+                    $notifications = implode(',', $notifications);
+                    $params['notifications'] = $notifications;
+                }
             }
 
-            $this->id = Database::insert($TBL_EXERCISES, $params);
+            $this->id = $this->iId = Database::insert($TBL_EXERCISES, $params);
 
             if ($this->id) {
                 $sql = "UPDATE $TBL_EXERCISES SET id = iid WHERE iid = {$this->id} ";
@@ -1750,6 +1759,8 @@ class Exercise
 
         // Updates the question position
         $this->update_question_positions();
+
+        return $this->iId;
     }
 
     /**
@@ -1899,18 +1910,18 @@ class Exercise
                 'text',
                 'exerciseTitle',
                 get_lang('ExerciseName'),
-                array('id' => 'exercise_title')
+                ['id' => 'exercise_title']
             );
         }
 
         $form->addElement('advanced_settings', 'advanced_params', get_lang('AdvancedParameters'));
         $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
 
-        $editor_config = array(
+        $editor_config = [
             'ToolbarSet' => 'TestQuestionDescription',
             'Width' => '100%',
             'Height' => '150',
-        );
+        ];
         if (is_array($type)) {
             $editor_config = array_merge($editor_config, $type);
         }
@@ -2452,7 +2463,6 @@ class Exercise
                 }
 
                 $form->addGroup($group, '', [get_lang('EmailNotifications')]);
-
             }
 
             $form->addCheckBox(
@@ -2461,7 +2471,7 @@ class Exercise
                 get_lang('UpdateTitleInLps')
             );
 
-            $defaults = array();
+            $defaults = [];
             if (api_get_setting('search_enabled') === 'true') {
                 require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
 
@@ -2471,15 +2481,15 @@ class Exercise
 
                 foreach ($specific_fields as $specific_field) {
                     $form->addElement('text', $specific_field['code'], $specific_field['name']);
-                    $filter = array(
+                    $filter = [
                         'c_id' => api_get_course_int_id(),
                         'field_id' => $specific_field['id'],
                         'ref_id' => $this->id,
-                        'tool_id' => "'".TOOL_QUIZ."'"
-                    );
-                    $values = get_specific_field_values_list($filter, array('value'));
+                        'tool_id' => "'".TOOL_QUIZ."'",
+                    ];
+                    $values = get_specific_field_values_list($filter, ['value']);
                     if (!empty($values)) {
-                        $arr_str_values = array();
+                        $arr_str_values = [];
                         foreach ($values as $value) {
                             $arr_str_values[] = $value['value'];
                         }
@@ -3513,12 +3523,12 @@ class Exercise
                 WHERE c_id = $course_id AND question_id = $questionId";
         $res_answer = Database::query($sql);
 
-        $answerMatching = array();
+        $answerMatching = [];
         while ($real_answer = Database::fetch_array($res_answer)) {
             $answerMatching[$real_answer['id_auto']] = $real_answer['answer'];
         }
 
-        $real_answers = array();
+        $real_answers = [];
         $quiz_question_options = Question::readQuestionOption(
             $questionId,
             $course_id
@@ -3526,7 +3536,7 @@ class Exercise
 
         $organs_at_risk_hit = 0;
         $questionScore = 0;
-        $answer_correct_array = array();
+        $answer_correct_array = [];
         $orderedHotspots = [];
 
         if ($answerType == HOT_SPOT || $answerType == ANNOTATION) {
@@ -3723,16 +3733,15 @@ class Exercise
                     break;
                 case MULTIPLE_ANSWER_COMBINATION:
                     if ($from_database) {
+                        $choice = [];
                         $sql = "SELECT answer FROM $TBL_TRACK_ATTEMPT
                                 WHERE exe_id = $exeId AND question_id= $questionId";
                         $resultans = Database::query($sql);
                         while ($row = Database::fetch_array($resultans)) {
-                            $ind = $row['answer'];
-                            $choice[$ind] = 1;
+                            $choice[$row['answer']] = 1;
                         }
 
                         $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null;
-
                         if ($answerCorrect == 1) {
                             if ($studentChoice) {
                                 $real_answers[$answerId] = true;
@@ -3748,7 +3757,6 @@ class Exercise
                         }
                     } else {
                         $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null;
-
                         if ($answerCorrect == 1) {
                             if ($studentChoice) {
                                 $real_answers[$answerId] = true;
@@ -3805,7 +3813,7 @@ class Exercise
                         $answer = '';
                         $j = 0;
                         //initialise answer tags
-                        $user_tags = $correct_tags = $real_text = array();
+                        $user_tags = $correct_tags = $real_text = [];
                         // the loop will stop at the end of the text
                         while (1) {
                             // quits the loop if there are no more blanks (detect '[')
@@ -3855,7 +3863,7 @@ class Exercise
                         }
                         $answer = '';
                         $real_correct_tags = $correct_tags;
-                        $chosen_list = array();
+                        $chosen_list = [];
 
                         for ($i = 0; $i < count($real_correct_tags); $i++) {
                             if ($i == 0) {
@@ -3872,7 +3880,8 @@ class Exercise
                                     // 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
+                                    // 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 {
@@ -3890,8 +3899,9 @@ class Exercise
                                     $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
+                                } 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 {
@@ -3942,14 +3952,28 @@ class Exercise
                                 }
 
                                 $isAnswerCorrect = 0;
-                                if (FillBlanks::isGoodStudentAnswer($studentAnswer, $correctAnswer)) {
+                                if (FillBlanks::isStudentAnswerGood($studentAnswer, $correctAnswer, $from_database)) {
                                     // gives the related weighting to the student
                                     $questionScore += $answerWeighting[$i];
                                     // increments total score
                                     $totalScore += $answerWeighting[$i];
                                     $isAnswerCorrect = 1;
                                 }
-                                $listCorrectAnswers['studentanswer'][$i] = $studentAnswer;
+
+                                $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['studentanswer'][$i] = $studentAnswerToShow;
                                 $listCorrectAnswers['studentscore'][$i] = $isAnswerCorrect;
                             }
                         } else {
@@ -3959,13 +3983,30 @@ class Exercise
                             // for every teacher answer, check if there is a student answer
                             for ($i = 0; $i < count($listStudentAnswerTemp); $i++) {
                                 $studentAnswer = trim($listStudentAnswerTemp[$i]);
+                                $studentAnswerToShow = $studentAnswer;
+
                                 $found = false;
                                 for ($j = 0; $j < count($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 (FillBlanks::isGoodStudentAnswer(
+                                        if (FillBlanks::isStudentAnswerGood(
                                             $studentAnswer,
-                                            $correctAnswer
+                                            $correctAnswer,
+                                            $from_database
                                         )
                                         ) {
                                             $questionScore += $answerWeighting[$i];
@@ -3975,7 +4016,7 @@ class Exercise
                                         }
                                     }
                                 }
-                                $listCorrectAnswers['studentanswer'][$i] = $studentAnswer;
+                                $listCorrectAnswers['studentanswer'][$i] = $studentAnswerToShow;
                                 if (!$found) {
                                     $listCorrectAnswers['studentscore'][$i] = 0;
                                 } else {
@@ -3986,6 +4027,10 @@ class Exercise
                         $answer = FillBlanks::getAnswerInStudentAttempt(
                             $listCorrectAnswers
                         );
+
+                        if ($saved_results) {
+                            //var_dump($listCorrectAnswers);
+                        }
                     }
                     break;
                 case CALCULATED_ANSWER:
@@ -3996,13 +4041,13 @@ class Exercise
                     for ($k = 0; $k < $last; $k++) {
                         $answer .= $preArray[$k];
                     }
-                    $answerWeighting = array($answerWeighting);
+                    $answerWeighting = [$answerWeighting];
                     // we save the answer because it will be modified
                     $temp = $answer;
                     $answer = '';
                     $j = 0;
                     //initialise answer tags
-                    $userTags = $correctTags = $realText = array();
+                    $userTags = $correctTags = $realText = [];
                     // the loop will stop at the end of the text
                     while (1) {
                         // quits the loop if there are no more blanks (detect '[')

+ 128 - 87
main/exercise/fill_blanks.class.php

@@ -10,13 +10,13 @@
  **/
 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_MENU = 1;
     const FILL_THE_BLANK_SEVERAL_ANSWER = 2;
 
+    public static $typePicture = 'fill_in_blanks.png';
+    public static $explanationLangVar = 'FillBlanks';
+
     /**
      * Constructor
      */
@@ -32,7 +32,7 @@ class FillBlanks extends Question
      */
     public function createAnswersForm($form)
     {
-        $defaults = array();
+        $defaults = [];
         if (!empty($this->id)) {
             $objectAnswer = new Answer($this->id);
             $answer = $objectAnswer->selectAnswer(1);
@@ -42,7 +42,7 @@ class FillBlanks extends Question
             } else {
                 $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['select_separator'] = $listAnswersInfo['blankseparatornumber'];
             $blankSeparatorNumber = $listAnswersInfo['blankseparatornumber'];
@@ -54,7 +54,6 @@ class FillBlanks extends Question
 
         $blankSeparatorStart = self::getStartSeparator($blankSeparatorNumber);
         $blankSeparatorEnd = self::getEndSeparator($blankSeparatorNumber);
-
         $setWeightAndSize = '';
         if (isset($listAnswersInfo) && count($listAnswersInfo['tabweighting']) > 0) {
             foreach ($listAnswersInfo['tabweighting'] as $i => $weighting) {
@@ -97,13 +96,16 @@ class FillBlanks extends Question
                                 
                 // disable the save button, if not blanks have been created
                 $("button").attr("disabled", "disabled");
-                $("#defineoneblank").show();                
+                $("#defineoneblank").show();      
+                
                 var blanks = answer.match(eval(blanksRegexp));             
                 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 += "<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 += "<table class=\"data_table\">";
+                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) {
                     for (var i=0; i < blanks.length; i++) {
@@ -133,15 +135,16 @@ class FillBlanks extends Question
                             var value = document.getElementById("weighting["+i+"]").value;
                         } else {
                             var value = "1";    
-                        }                                            
+                        }                
+                        var blanksWithColor = trimBlanksBetweenSeparator(blanks[i], blankSeparatorStart, blankSeparatorEnd, 1);
                         
                         fields += "<tr>";
-                        fields += "<td>"+blanks[i]+"</td>";
-                        fields += "<td><input style=\"width:35px\" value=\""+value+"\" type=\"text\" id=\"weighting["+i+"]\" name=\"weighting["+i+"]\" /></td>";
+                        fields += "<td>"+blanksWithColor+"</td>";
+                        fields += "<td><input class=\"form-control\" style=\"width:60px\" value=\""+value+"\" type=\"text\" id=\"weighting["+i+"]\" name=\"weighting["+i+"]\" /></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=\"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 += "</td>";
                         fields += "</tr>";
@@ -152,7 +155,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) {
                      if (firstTime == false) {
                         value = data.value;                        
@@ -235,7 +239,7 @@ class FillBlanks extends Question
                 $("#samplesize\\\["+inIdNum+"\\\]").outerWidth(newWidth);
                 $("#sizeofinput\\\["+inIdNum+"\\\]").attr("value", newWidth);
                 
-                updateOrder(blanks); 
+                updateOrder(blanks);
             }
 
             function removeForbiddenChars(inTxt)
@@ -279,27 +283,44 @@ class FillBlanks extends Question
 
             // this function is the same than the PHP one
             // if modify it modify the php one getAllowedSeparator
-            function getSeparatorFromNumber(innumber)
+            function getSeparatorFromNumber(number)
             {
-                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];
+                var separator = new Array();
+                separator[0] = new Array("[", "]");
+                separator[1] = new Array("{", "}");
+                separator[2] = new Array("(", ")");
+                separator[3] = new Array("*", "*");
+                separator[4] = new Array("#", "#");
+                separator[5] = new Array("%", "%");
+                separator[6] = new Array("$", "$");
+                return separator[number];
             }
 
-            function trimBlanksBetweenSeparator(inTxt, inSeparatorStart, inSeparatorEnd)
+            function trimBlanksBetweenSeparator(inTxt, inSeparatorStart, inSeparatorEnd, addColor)
             {
                 var result = inTxt
                 result = result.replace(inSeparatorStart, "");
                 result = result.replace(inSeparatorEnd, "");
                 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;
             }
+            
         </script>';
 
         // answer
@@ -312,7 +333,7 @@ class FillBlanks extends Question
             'answer',
             Display::return_icon('fill_field.png'),
             ['id' => 'answer'],
-            array('ToolbarSet' => 'TestQuestionDescription')
+            ['ToolbarSet' => 'TestQuestionDescription']
         );
         $form->addRule('answer', get_lang('GiveText'), 'required');
 
@@ -321,14 +342,15 @@ class FillBlanks extends Question
         $form->addElement(
             'select',
             'select_separator',
-            get_lang("SelectFillTheBlankSeparator"),
+            get_lang('SelectFillTheBlankSeparator'),
             self::getAllowedSeparatorForSelect(),
-            ' id="select_separator" style="width:150px" onchange="changeBlankSeparator()" '
+            ' id="select_separator" style="width:150px" class="selectpicker" onchange="changeBlankSeparator()" '
         );
         $form->addLabel(
             null,
             '<input type="button" onclick="updateBlanks()" value="'.get_lang('RefreshBlanks').'" class="btn btn-default" />'
         );
+
         $form->addHtml('<div id="blanks_weighting"></div>');
 
         global $text;
@@ -424,7 +446,7 @@ class FillBlanks extends Question
                     $answer .= ",";
                 }
                 // calculate the global weighting for the question
-                $this -> weighting += $form->getSubmitValue('weighting['.$i.']');
+                $this->weighting += (float) $form->getSubmitValue('weighting['.$i.']');
             }
 
             // input width
@@ -499,6 +521,7 @@ class FillBlanks extends Question
     ) {
         $inTabTeacherSolution = $listAnswersInfo['tabwords'];
         $inTeacherSolution = $inTabTeacherSolution[$inBlankNumber];
+
         switch (self::getFillTheBlankAnswerType($inTeacherSolution)) {
             case self::FILL_THE_BLANK_MENU:
                 $selected = '';
@@ -512,19 +535,12 @@ class FillBlanks extends Question
 
                 $resultOptions = ['' => '--'];
                 foreach ($listMenu as $item) {
-                    $item = self::trimOption($item);
-                    $resultOptions[$item] = $item;
+                    $resultOptions[sha1($item)] = $item;
                 }
 
-                for ($k = 0; $k < count($listMenu); $k++) {
-                    if ($correctItem == $listMenu[$k]) {
-                        $selected = $k;
-
-                        break;
-                    }
-                    // if in teacher view, display the first item by default, which is the right answer
-                    if ($k == 0 && !$displayForStudent) {
-                        $selected = $k;
+                foreach ($resultOptions as $key => $value) {
+                    if ($correctItem == $value) {
+                        $selected = $key;
 
                         break;
                     }
@@ -555,12 +571,17 @@ class FillBlanks extends Question
         return $result;
     }
 
+    /**
+     * Removes double spaces between words
+     * @param string $text
+     * @return string
+     */
     private static function trimOption($text)
     {
-        $converted = strtr($text, array_flip(get_html_translation_table(HTML_ENTITIES, ENT_QUOTES)));
-        $trimmed = trim($converted, chr(0xC2).chr(0xA0).' ');
+        $text = trim($text);
+        $text = preg_replace("/\s+/", " ", $text);
 
-        return $trimmed;
+        return $text;
     }
 
     /**
@@ -574,8 +595,13 @@ class FillBlanks extends Question
     public static function getFillTheBlankMenuAnswers($correctAnswer, $displayForStudent)
     {
         $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) {
-            shuffle($list);
+            shuffle_assoc($list);
         }
 
         return $list;
@@ -620,33 +646,49 @@ class FillBlanks extends Question
      * 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
      * eg : studentAnswer = 'Un' and correctAnswer = 'Un||1||un'
-     * @param string $studentAnswer [studentanswer] of the info array of the answer field
-     * @param string $correctAnswer [tabwords] of the info array of the answer field
-     *
+     * @param string $studentAnswer [student_answer] 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
      */
-    public static function isGoodStudentAnswer($studentAnswer, $correctAnswer)
+    public static function isStudentAnswerGood($studentAnswer, $correctAnswer, $fromDatabase = false)
     {
+        $result = false;
         switch (self::getFillTheBlankAnswerType($correctAnswer)) {
             case self::FILL_THE_BLANK_MENU:
                 $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;
             case self::FILL_THE_BLANK_SEVERAL_ANSWER:
                 // the answer must be one of the choice made
                 $listSeveral = self::getFillTheBlankSeveralAnswers($correctAnswer);
-
-                $listSeveral = array_map(function($item) {
-                    return self::trimOption($item);
-                }, $listSeveral);
-
+                $listSeveral = array_map(
+                    function ($item) {
+                        return self::trimOption($item);
+                    },
+                    $listSeveral
+                );
                 $result = in_array($studentAnswer, $listSeveral);
                 break;
             case self::FILL_THE_BLANK_STANDARD:
             default:
+                $correctAnswer = api_html_entity_decode($correctAnswer);
+                $studentAnswer = htmlspecialchars($studentAnswer);
                 $result = $studentAnswer == self::trimOption($correctAnswer);
+
+
                 break;
         }
+        //var_dump($result);
 
         return $result;
     }
@@ -658,9 +700,9 @@ class FillBlanks extends Question
      */
     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;
-        } elseif (api_strpos($correctAnswer, "||")) {
+        } elseif (api_strpos($correctAnswer, '||')) {
             return self::FILL_THE_BLANK_SEVERAL_ANSWER;
         } else {
             return self::FILL_THE_BLANK_STANDARD;
@@ -701,20 +743,20 @@ class FillBlanks extends Question
 
         $listAnswerResults['systemstring'] = $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]);
 
         if (count($listArobaseSplit) < 2) {
             $listArobaseSplit[1] = '';
         }
 
-        // take the complete string except after the last '::'
+        // 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();
+            $listSizeOfInput = [];
             for ($i = 0; $i < count($listWeightings); $i++) {
                 $listSizeOfInput[] = 200;
             }
@@ -757,12 +799,12 @@ class FillBlanks extends Question
                     }
                     $value = trim($value, $trimChars);
                 },
-                array($blankCharStart, $blankCharEnd)
+                [$blankCharStart, $blankCharEnd]
             );
             $listAnswerResults['tabwords'] = $listWords[0];
         }
 
-        // get all common words
+        // Get all common words
         $commonWords = api_preg_replace(
             '/'.$blankCharStartForRegexp.'[^'.$blankCharEndForRegexp.']*'.$blankCharEndForRegexp.'/',
             "::",
@@ -771,9 +813,8 @@ class FillBlanks extends Question
 
         // if student answer, the second [] is the student answer,
         // the third is if student scored or not
-        $listBrackets = array();
-        $listWords = array();
-
+        $listBrackets = [];
+        $listWords = [];
         if ($isStudentAnswer) {
             for ($i = 0; $i < count($listAnswerResults['tabwords']); $i++) {
                 $listBrackets[] = $listAnswerResults['tabwordsbracket'][$i];
@@ -797,7 +838,6 @@ class FillBlanks extends Question
         }
 
         $listAnswerResults['commonwords'] = explode("::", $commonWords);
-        //echo strip_tags($commonWords);
 
         return $listAnswerResults;
     }
@@ -839,7 +879,7 @@ class FillBlanks extends Question
         $courseId = api_get_course_int_id();
         // If no user has answered questions, no need to go further. Return empty array.
         if (empty($studentsIdList)) {
-            return array();
+            return [];
         }
         // request to have all the answers of student for this question
         // student may have doing it several time
@@ -861,7 +901,7 @@ class FillBlanks extends Question
         ';
 
         $res = Database::query($sql);
-        $tabUserResult = array();
+        $tabUserResult = [];
         // foreach attempts for all students starting with his older attempt
         while ($data = Database::fetch_array($res)) {
             $tabAnswer = self::getAnswerInfo($data['answer'], true);
@@ -1039,17 +1079,15 @@ class FillBlanks extends Question
      */
     public static function getAllowedSeparator()
     {
-        $fillBlanksAllowedSeparator = array(
-            array('[', ']'),
-            array('{', '}'),
-            array('(', ')'),
-            array('*', '*'),
-            array('#', '#'),
-            array('%', '%'),
-            array('$', '$'),
-        );
-
-        return $fillBlanksAllowedSeparator;
+        return [
+            ['[', ']'],
+            ['{', '}'],
+            ['(', ')'],
+            ['*', '*'],
+            ['#', '#'],
+            ['%', '%'],
+            ['$', '$'],
+        ];
     }
 
     /**
@@ -1085,10 +1123,10 @@ class FillBlanks extends Question
      */
     public static function getAllowedSeparatorForSelect()
     {
-        $listResults = array();
-        $fillBlanksAllowedSeparator = self::getAllowedSeparator();
-        for ($i = 0; $i < count($fillBlanksAllowedSeparator); $i++) {
-            $listResults[] = $fillBlanksAllowedSeparator[$i][0]."...".$fillBlanksAllowedSeparator[$i][1];
+        $listResults = [];
+        $allowedSeparator = self::getAllowedSeparator();
+        foreach ($allowedSeparator as $part) {
+            $listResults[] = $part[0]."...".$part[1];
         }
 
         return $listResults;
@@ -1257,7 +1295,9 @@ class FillBlanks extends Question
      * return HTML code for correct answer
      * @param string $answer
      * @param string $correct
-     * @param bool   $resultsDisabled
+     * @param string $feedbackType
+     * @param bool $resultsDisabled
+     * @param bool $showTotalScoreAndUserChoices
      *
      * @return string
      */
@@ -1282,6 +1322,7 @@ class FillBlanks extends Question
      * return HTML code for wrong answer
      * @param string $answer
      * @param string $correct
+     * @param string $feedbackType
      * @param bool   $resultsDisabled
      *
      * @return string
@@ -1316,8 +1357,8 @@ class FillBlanks extends Question
         $isCorrect = true;
 
         foreach ($correctAnswerList as $i => $correctAnswer) {
-            $isGoodStudentAnswer = self::isGoodStudentAnswer($studentAnswer[$i], $correctAnswer);
-            $isCorrect = $isCorrect && $isGoodStudentAnswer;
+            $value = self::isStudentAnswerGood($studentAnswer[$i], $correctAnswer);
+            $isCorrect = $isCorrect && $value;
         }
 
         return $isCorrect;