/**
  * Display the exercise results
  * @param int  $exe_id
  * @param bool $saveUserResult save users results (true) or just show the results (false)
  * @param bool $returnExerciseResult return array with exercise result info
  * @return mixed
  */
 public function displayQuestionListByAttempt($exe_id, $saveUserResult = false, $returnExerciseResult = false)
 {
     global $origin, $debug;
     //Getting attempt info
     $exercise_stat_info = $this->getStatTrackExerciseInfoByExeId($exe_id);
     //Getting question list
     $question_list = array();
     if (!empty($exercise_stat_info['data_tracking'])) {
         $question_list = explode(',', $exercise_stat_info['data_tracking']);
     } else {
         //Try getting the question list only if save result is off
         if ($saveUserResult == false) {
             $question_list = $this->selectQuestionList();
         }
         error_log("Data tracking is empty! exe_id: {$exe_id}");
     }
     $counter = 1;
     $total_score = 0;
     $total_weight = 0;
     $exercise_content = null;
     //Hide results
     $show_results = false;
     $show_only_score = false;
     if ($this->results_disabled == RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS) {
         $show_results = true;
     }
     if (in_array($this->results_disabled, array(RESULT_DISABLE_SHOW_SCORE_ONLY, RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES))) {
         $show_only_score = true;
     }
     if ($show_results || $show_only_score) {
         $user_info = api_get_user_info($exercise_stat_info['exe_user_id']);
         // Shows exercise header.
         echo $this->show_exercise_result_header($user_info['complete_name'], api_convert_and_format_date($exercise_stat_info['start_date'], DATE_TIME_FORMAT_LONG), $exercise_stat_info['duration']);
     }
     // Display text when test is finished #4074 and for LP #4227
     $end_of_message = $this->selectTextWhenFinished();
     if (!empty($end_of_message)) {
         Display::display_normal_message($end_of_message, false);
         echo "<div class='clear'>&nbsp;</div>";
     }
     $question_list_answers = array();
     $media_list = array();
     $category_list = array();
     $tempParentId = null;
     $mediaCounter = 0;
     $exerciseResultInfo = array();
     // Loop over all question to show results for each of them, one by one
     if (!empty($question_list)) {
         if ($debug) {
             error_log('Looping question_list ' . print_r($question_list, 1));
         }
         foreach ($question_list as $questionId) {
             // Creates a temporary Question object
             $objQuestionTmp = Question::read($questionId);
             // This variable commes from exercise_submit_modal.php
             ob_start();
             $hotspot_delineation_result = null;
             // We're inside *one* question. Go through each possible answer for this question
             $result = $this->manageAnswers($exercise_stat_info['exe_id'], $questionId, null, 'exercise_result', array(), $saveUserResult, true, $show_results, $hotspot_delineation_result);
             if (empty($result)) {
                 continue;
             }
             $total_score += $result['score'];
             $total_weight += $result['weight'];
             $question_list_answers[] = array('question' => $result['open_question'], 'answer' => $result['open_answer'], 'answer_type' => $result['answer_type']);
             $my_total_score = $result['score'];
             $my_total_weight = $result['weight'];
             // Category report
             $category_was_added_for_this_test = false;
             $categoryExerciseList = $this->getListOfCategoriesWithQuestionForTest();
             $category_list = array();
             if (isset($categoryExerciseList) && !empty($categoryExerciseList)) {
                 foreach ($categoryExerciseList as $category_id => $categoryInfo) {
                     if (!isset($category_list[$category_id])) {
                         $category_list[$category_id] = array();
                         $category_list[$category_id]['score'] = 0;
                         $category_list[$category_id]['total'] = 0;
                     }
                     $category_list[$category_id]['score'] += $my_total_score;
                     $category_list[$category_id]['total'] += $my_total_weight;
                     $category_was_added_for_this_test = true;
                 }
             }
             // No category for this question!
             if ($category_was_added_for_this_test == false) {
                 if (!isset($category_list['none'])) {
                     $category_list['none'] = array();
                     $category_list['none']['score'] = 0;
                     $category_list['none']['total'] = 0;
                 }
                 $category_list['none']['score'] += $my_total_score;
                 $category_list['none']['total'] += $my_total_weight;
             }
             if ($this->selectPropagateNeg() == 0 && $my_total_score < 0) {
                 $my_total_score = 0;
             }
             $comnt = null;
             if ($show_results) {
                 $comnt = get_comments($exe_id, $questionId);
                 if (!empty($comnt)) {
                     echo '<b>' . get_lang('Feedback') . '</b>';
                     echo '<div id="question_feedback">' . $comnt . '</div>';
                 }
             }
             $score = array();
             $score['result'] = get_lang('Score') . " : " . ExerciseLib::show_score($my_total_score, $my_total_weight, false, true);
             $score['pass'] = $my_total_score >= $my_total_weight ? true : false;
             $score['score'] = $my_total_score;
             $score['weight'] = $my_total_weight;
             $score['comments'] = $comnt;
             $exerciseResultInfo[$questionId]['score'] = $score;
             $exerciseResultInfo[$questionId]['details'] = $result;
             // If no results we hide the results
             if ($show_results == false) {
                 $score = array();
             }
             $contents = ob_get_clean();
             $question_content = '<div class="question_row">';
             if ($show_results) {
                 $show_media = false;
                 $counterToShow = $counter;
                 if ($objQuestionTmp->parent_id != 0) {
                     if (!in_array($objQuestionTmp->parent_id, $media_list)) {
                         $media_list[] = $objQuestionTmp->parent_id;
                         $show_media = true;
                     }
                     if ($tempParentId == $objQuestionTmp->parent_id) {
                         $mediaCounter++;
                     } else {
                         $mediaCounter = 0;
                     }
                     $counterToShow = chr(97 + $mediaCounter);
                     $tempParentId = $objQuestionTmp->parent_id;
                 }
                 // Shows question title an description.
                 $question_content .= $objQuestionTmp->return_header(null, $counterToShow, $score, $show_media, $this->getHideQuestionTitle());
                 // display question category, if any
                 $question_content .= TestCategory::getCategoryNamesForQuestion($questionId, null, true, $this->categoryMinusOne);
             }
             $counter++;
             $question_content .= $contents;
             $question_content .= '</div>';
             $exercise_content .= $question_content;
         }
         // end foreach() block that loops over all questions
     }
     $total_score_text = null;
     if ($returnExerciseResult) {
         return $exerciseResultInfo;
     }
     if ($origin != 'learnpath') {
         if ($show_results || $show_only_score) {
             $total_score_text .= $this->get_question_ribbon($total_score, $total_weight, true);
         }
     }
     if (!empty($category_list) && ($show_results || $show_only_score)) {
         //Adding total
         $category_list['total'] = array('score' => $total_score, 'total' => $total_weight);
         echo TestCategory::get_stats_table_by_attempt($this->id, $category_list, $this->categoryMinusOne);
     }
     echo $total_score_text;
     echo $exercise_content;
     if (!$show_only_score) {
         echo $total_score_text;
     }
     if ($saveUserResult) {
         // Tracking of results
         $learnpath_id = $exercise_stat_info['orig_lp_id'];
         $learnpath_item_id = $exercise_stat_info['orig_lp_item_id'];
         $learnpath_item_view_id = $exercise_stat_info['orig_lp_item_view_id'];
         if (api_is_allowed_to_session_edit()) {
             update_event_exercise($exercise_stat_info['exe_id'], $this->selectId(), $total_score, $total_weight, api_get_session_id(), $learnpath_id, $learnpath_item_id, $learnpath_item_view_id, $exercise_stat_info['exe_duration'], '', array());
         }
         // Send notification.
         if (!api_is_allowed_to_edit(null, true)) {
             $isSuccess = ExerciseLib::is_success_exercise_result($total_score, $total_weight, $this->selectPassPercentage());
             $this->sendCustomNotification($exe_id, $exerciseResultInfo, $isSuccess);
             $this->sendNotificationForOpenQuestions($question_list_answers, $origin, $exe_id);
             $this->sendNotificationForOralQuestions($question_list_answers, $origin, $exe_id);
         }
     }
 }
         $durationTime = Session::read('duration_time');
         if (isset($durationTime[$key]) && !empty($durationTime[$key])) {
             $duration = $now - $durationTime[$key];
             if (!empty($exercise_stat_info['exe_duration'])) {
                 $duration += $exercise_stat_info['exe_duration'];
             }
             $duration = intval($duration);
         } else {
             if (!empty($exercise_stat_info['exe_duration'])) {
                 $duration = $exercise_stat_info['exe_duration'];
             }
         }
         $durationTime = array($key => time());
         Session::write('duration_time', $durationTime);
         // $_SESSION['duration_time'][$key] = time();
         update_event_exercise($exe_id, $objExercise->selectId(), $total_score, $total_weight, $session_id, $exercise_stat_info['orig_lp_id'], $exercise_stat_info['orig_lp_item_id'], $exercise_stat_info['orig_lp_item_view_id'], $duration, 'incomplete', $remind_list);
         // Destruction of the Question object
         unset($objQuestionTmp);
         if ($debug) {
             error_log(" -- end question -- ");
         }
     }
     if ($debug) {
         error_log(" ------ end ajax call ------- ");
     }
 }
 if ($objExercise->type == ONE_PER_PAGE) {
     echo 'one_per_page';
     exit;
 }
 echo 'ok';