Exercise result UI changes

- Change feedback message color, centralized in one function.
- "notCorrectedYet" message centralized in one function
- Add message "Temporary score: %s open question(s) not corrected yet"
  if open/oral questions in exercise
- Fix function name get_question_ribbon -> getTotalQuestionRibbon
- Rename function name (to camelCase)
- Create new function getQuestionRibbon
- Remove un used functions.
- Add new "rib-warning" class if questions is "Not reviewed yet" (oral, free)

see BT#12303
pull/2487/head
jmontoyaa 8 years ago
parent 3d996d4760
commit 6150fe7d70
  1. 44
      app/Resources/public/css/base.css
  2. 339
      main/exercise/exercise.class.php
  3. 23
      main/exercise/exercise_show.php
  4. 6
      main/exercise/freeanswer.class.php
  5. 3
      main/exercise/oral_expression.class.php
  6. 22
      main/exercise/question.class.php
  7. 170
      main/inc/lib/exercise.lib.php
  8. 33
      main/inc/lib/exercise_show_functions.lib.php
  9. 1
      main/lang/english/trad4all.inc.php
  10. 3
      main/lp/lp_view.php

@ -92,7 +92,6 @@ a.thumbnail:hover{
.page-course{
padding: 2% 3%;
}
/*------------------------*/
.cursor-pointer {
cursor: pointer;
}
@ -127,7 +126,7 @@ a.thumbnail:hover{
border-radius: 0;
border: none;
}
header{
header {
padding-top: 20px;
}
.blackboard_show {
@ -871,7 +870,6 @@ a.personal_agenda:hover, a.personal_agenda:hover {
}
/* Categories courses*/
#course-picture {
position:absolute;
top:8%;
@ -1110,7 +1108,6 @@ div.attendance-calendar-add div.row div.formw,div.attendance-calendar-edit div.r
padding: 0px;
}
#message {
margin: 0 auto;
text-align: center;
@ -1407,7 +1404,6 @@ div.admin_section h4 {
.grid_title {float:left;width:30%;text-align:center}
.grid_nav {float:left;width:35%;text-align:right}
/* Groups boxes */
.toolbar-groups{
margin-bottom: 30px;
@ -1426,7 +1422,6 @@ div.admin_section h4 {
.group_invitation_grid_element_1 { width:100px; float:left; text-align:left;margin-bottom:5px;}
.group_invitation_grid_element_2 { width:150px; float:left;}
/* home group boxes */
.home_group_grid_container {
@ -1503,7 +1498,6 @@ div.admin_section h4 {
.search_user_grid_element_3 { width:100%; text-align:center;}
/*SEARCH GROUP*/
.search_group_grid_item {
float:left;
width:345px;
@ -1563,7 +1557,6 @@ div.admin_section h4 {
height:5px;
}
#lp_item_list .ui-state-highlight {
height:25px;
background: #EEEEEE;
@ -1825,25 +1818,25 @@ div.admin_section h4 {
.question_options input[type="text"] {
padding: 6px 12px;
margin:2px 2px 2px 0px;
margin: 2px 2px 2px 0px;
vertical-align: middle;
display: inline-block;
height: 34px;
line-height: 1.42857;
border: 1px solid #CCCCCC;
border-radius: 4px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
color: #555555;
font-weight: bold;
background-color: #FCF8D6;
border-radius: 4px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
color: #555555;
font-weight: bold;
background-color: #FCF8D6;
}
.question_options input[type="text"]:focus{
border-color:#66AFE9;
background-color: #ffffff;
outline: 0px none;
box-shadow:0px 1px 1px rgba(0, 0, 0, 0.075) inset, 0px 0px 8px rgba(102, 175, 233, 0.6) ;
border-color: #66AFE9;
background-color: #ffffff;
outline: 0px none;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.075) inset, 0px 0px 8px rgba(102, 175, 233, 0.6);
}
.exercise_description {
@ -1993,6 +1986,13 @@ div.admin_section h4 {
float: left;
}
.ribbon .rib-warning {
background: orange;
border-top: none;
border-bottom: none;
float: left;
}
.ribbon .rib-gray {
background: #cccccc;
background-image: -ms-linear-gradient(top, #bbbbbb, #cccccc);
@ -2059,6 +2059,10 @@ div.admin_section h4 {
border-color: #ccc transparent transparent transparent;
}
.ribbon .rib-warning::before {
border-color: darkorange transparent transparent transparent;
}
.ribbon .rib::before {left: 0;}
.ribbon .rib::after {right: 0;}
@ -6271,7 +6275,7 @@ ul#toolnavbox-two li a.btn{
width: 100px;
}
.form-horizontal .radio{
padding-left: 5px;
padding-left: 5px;
}
.checkbox input[type="checkbox"]{
margin-left: -24px;

@ -7123,345 +7123,6 @@ class Exercise
}
}
/**
* @param int $exeId
* @return array
*/
public function returnQuestionListByAttempt($exeId)
{
return $this->displayQuestionListByAttempt($exeId, false, true);
}
/**
* 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;
}
$showScoreOptions = [
RESULT_DISABLE_SHOW_SCORE_ONLY,
RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES,
RESULT_DISABLE_SHOW_SCORE_ATTEMPT_SHOW_ANSWERS_LAST_ATTEMPT
];
if (in_array($this->results_disabled, $showScoreOptions)) {
$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)) {
echo Display::return_message($end_of_message, 'normal', 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 comes 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()) {
Event::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);
}
}
}
/**
* Returns an HTML ribbon to show on top of the exercise result, with
* colouring depending on the success or failure of the student
* @param integer $score
* @param integer $weight
* @param bool $check_pass_percentage
* @return string
*/
public function get_question_ribbon($score, $weight, $check_pass_percentage = false)
{
$eventMessage = null;
$ribbon = '<div class="question_row">';
$ribbon .= '<div class="ribbon">';
if ($check_pass_percentage) {
$is_success = ExerciseLib::is_success_exercise_result($score, $weight, $this->selectPassPercentage());
// Color the final test score if pass_percentage activated
$ribbon_total_success_or_error = '';
if (ExerciseLib::isPassPercentageEnabled($this->selectPassPercentage())) {
if ($is_success) {
$eventMessage = $this->getOnSuccessMessage();
$ribbon_total_success_or_error = ' ribbon-total-success';
} else {
$eventMessage = $this->getOnFailedMessage();
$ribbon_total_success_or_error = ' ribbon-total-error';
}
}
$ribbon .= '<div class="rib rib-total '.$ribbon_total_success_or_error.'">';
} else {
$ribbon .= '<div class="rib rib-total">';
}
$ribbon .= '<h3>'.get_lang('YourTotalScore').":&nbsp;";
$ribbon .= ExerciseLib::show_score($score, $weight, false, true);
$ribbon .= '</h3>';
$ribbon .= '</div>';
if ($check_pass_percentage) {
$ribbon .= ExerciseLib::show_success_message($score, $weight, $this->selectPassPercentage());
}
$ribbon .= '</div>';
$ribbon .= '</div>';
$ribbon .= $eventMessage;
return $ribbon;
}
/**
* Returns an array of categories details for the questions of the current
* exercise.

@ -349,6 +349,7 @@ if (!empty($maxEditors) && count($questionList) > $maxEditors) {
$useAdvancedEditor = false;
}
$countPendingQuestions = 0;
foreach ($questionList as $questionId) {
$choice = $exerciseResult[$questionId];
// destruction of the Question object
@ -367,7 +368,6 @@ foreach ($questionList as $questionId) {
}
$relPath = api_get_path(WEB_CODE_PATH);
switch ($answerType) {
case MULTIPLE_ANSWER_COMBINATION:
//no break
@ -702,7 +702,7 @@ foreach ($questionList as $questionId) {
if (empty($comnt)) {
echo '<br />';
} else {
echo '<div id="question_feedback">'.$comnt.'</div>';
echo ExerciseLib::getFeedbackText($comnt);
}
echo '</div>';
@ -741,7 +741,7 @@ foreach ($questionList as $questionId) {
echo '<br />';
if (!empty($comnt)) {
echo '<b>'.get_lang('Feedback').'</b>';
echo '<div id="question_feedback">'.$comnt.'</div>';
echo ExerciseLib::getFeedbackText($comnt);
}
}
@ -761,7 +761,7 @@ foreach ($questionList as $questionId) {
if ($questionScore == -1) {
$questionScore = 0;
echo Display::return_message(get_lang('notCorrectedYet'));
echo ExerciseLib::getNotCorrectedYetText();
}
} else {
$arrmarks[] = $questionId;
@ -822,7 +822,7 @@ foreach ($questionList as $questionId) {
$score = array();
if ($show_results) {
$score['result'] = get_lang('Score')." : ".ExerciseLib::show_score(
$score['result'] = ExerciseLib::show_score(
$my_total_score,
$my_total_weight,
false,
@ -835,11 +835,17 @@ foreach ($questionList as $questionId) {
$score['comments'] = isset($comnt) ? $comnt : null;
}
if (in_array($objQuestionTmp->type, [FREE_ANSWER, ORAL_EXPRESSION])) {
$check = $objQuestionTmp->isQuestionWaitingReview($score);
if ($check === false) {
$countPendingQuestions++;
}
}
unset($objAnswerTmp);
$i++;
$contents = ob_get_clean();
$question_content = '<div class="question_row">';
if ($show_results) {
@ -862,11 +868,12 @@ if ($origin != 'learnpath' || ($origin == 'learnpath' && isset($_GET['fb_type'])
if ($objExercise->selectPropagateNeg() == 0 && $my_total_score_temp < 0) {
$my_total_score_temp = 0;
}
$total_score_text .= ExerciseLib::get_question_ribbon(
$total_score_text .= ExerciseLib::getTotalScoreRibbon(
$objExercise,
$my_total_score_temp,
$totalWeighting,
true
true,
$countPendingQuestions
);
$total_score_text .= '</div>';
}

@ -56,11 +56,7 @@ class FreeAnswer extends Question
*/
public function return_header($feedback_type = null, $counter = null, $score = [])
{
if (!empty($score['comments']) || $score['score'] > 0) {
$score['revised'] = true;
} else {
$score['revised'] = false;
}
$score['revised'] = $this->isQuestionWaitingReview($score);
$header = parent::return_header($feedback_type, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'" >
<tr>

@ -70,8 +70,9 @@ class OralExpression extends Question
* @param null $score
* @return null|string
*/
function return_header($feedback_type = null, $counter = null, $score = null)
public function return_header($feedback_type = null, $counter = null, $score = null)
{
$score['revised'] = $this->isQuestionWaitingReview($score);
$header = parent::return_header($feedback_type, $counter, $score);
$header .= '<table class="'.$this->question_table_class.'">
<tr>

@ -1911,7 +1911,7 @@ abstract class Question
$class = '';
} else {
$score_label = get_lang('NotRevised');
$class = 'error';
$class = 'warning';
$weight = float_format($score['weight'], 1);
$score['result'] = " ? / ".$weight;
}
@ -1925,10 +1925,7 @@ abstract class Question
}
$header .= Display::page_subheader2($counter_label.". ".$this->question);
$header .= Display::div(
"<div class=\"rib rib-$class\"><h3>$score_label</h3></div> <h4> ".get_lang('Score').": {$score['result']}</h4>",
array('class' => 'ribbon')
);
$header .= ExerciseLib::getQuestionRibbon($class, $score_label, $score['result']);
if ($this->type != READING_COMPREHENSION) {
// Do not show the description (the text to read) if the question is of type READING_COMPREHENSION
$header .= Display::div($this->description, array('class' => 'question_description'));
@ -2175,4 +2172,19 @@ abstract class Question
}
return $swappedAnswer;
}
/**
* @param array $score
* @return bool
*/
public function isQuestionWaitingReview($score)
{
$isReview = false;
if (!empty($score['comments']) || $score['score'] > 0) {
$isReview = true;
}
return $isReview;
}
}

@ -114,7 +114,6 @@ class ExerciseLib
if (in_array($answerType, [MATCHING, DRAGGABLE, MATCHING_DRAGGABLE])) {
if ($answerType == DRAGGABLE) {
$isVertical = $objQuestionTmp->extra == 'v';
$s .= '
<div class="col-md-12 ui-widget ui-helper-clearfix">
<div class="clearfix">
@ -148,7 +147,6 @@ class ExerciseLib
}
$i = 1;
$select_items[0]['id'] = 0;
$select_items[0]['letter'] = '--';
$select_items[0]['answer'] = '';
@ -239,7 +237,6 @@ class ExerciseLib
} else {
$header .= Display::tag('th', $item);
}
}
if ($show_comment) {
$header .= Display::tag('th', get_lang('Feedback'));
@ -253,19 +250,17 @@ class ExerciseLib
}
if ($show_comment) {
if (
in_array(
$answerType,
array(
MULTIPLE_ANSWER,
MULTIPLE_ANSWER_COMBINATION,
UNIQUE_ANSWER,
UNIQUE_ANSWER_IMAGE,
UNIQUE_ANSWER_NO_OPTION,
GLOBAL_MULTIPLE_ANSWER
)
if (in_array(
$answerType,
array(
MULTIPLE_ANSWER,
MULTIPLE_ANSWER_COMBINATION,
UNIQUE_ANSWER,
UNIQUE_ANSWER_IMAGE,
UNIQUE_ANSWER_NO_OPTION,
GLOBAL_MULTIPLE_ANSWER,
)
) {
)) {
$header = Display::tag('th', get_lang('Options'));
if ($exercise_feedback == EXERCISE_FEEDBACK_TYPE_END) {
$header .= Display::tag('th', get_lang('Feedback'));
@ -302,7 +297,6 @@ class ExerciseLib
}
for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) {
$answer = $objAnswerTmp->selectAnswer($answerId);
$answerCorrect = $objAnswerTmp->isCorrect($answerId);
$numAnswer = $objAnswerTmp->selectAutoId($answerId);
@ -908,7 +902,6 @@ class ExerciseLib
if ($value == $selectedValue) {
break;
}
$selectedIndex++;
}
@ -994,7 +987,6 @@ HTML;
if ($answerCorrect != $chosen['answer']) {
continue;
}
$selectedValue = $chosen['answer'];
}
}
@ -1007,7 +999,6 @@ HTML;
if ($value == $selectedValue) {
break;
}
$selectedIndex++;
}
@ -1107,7 +1098,6 @@ HTML;
$s .= "</ul>";
$s .= "</div>"; //clearfix
$counterAnswer = 1;
$s .= $isVertical ? '' : '<div class="row">';
for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) {
@ -1313,7 +1303,6 @@ HOTSPOT;
if (!$only_questions) {
if ($show_title) {
TestCategory::displayCategoryAndTitle($objQuestionTmp->id);
echo $objQuestionTmp->getTitleToDisplay($current_item);
}
echo '
@ -1397,6 +1386,10 @@ HOTSPOT;
/**
* Validates the time control key
* @param int $exercise_id
* @param int $lp_id
* @param int $lp_item_id
* @return bool
*/
public static function exercise_time_control_is_valid(
$exercise_id,
@ -1437,6 +1430,10 @@ HOTSPOT;
/**
* Deletes the time control token
*
* @param int $exercise_id
* @param int $lp_id
* @param int $lp_item_id
*/
public static function exercise_time_control_delete(
$exercise_id,
@ -1454,8 +1451,11 @@ HOTSPOT;
/**
* Generates the time control key
*/
public static function get_time_control_key($exercise_id, $lp_id = 0, $lp_item_id = 0)
{
public static function get_time_control_key(
$exercise_id,
$lp_id = 0,
$lp_item_id = 0
) {
$exercise_id = intval($exercise_id);
$lp_id = intval($lp_id);
$lp_item_id = intval($lp_item_id);
@ -2066,7 +2066,6 @@ HOTSPOT;
}
}
$revisedLabel = '';
switch ($revised) {
case 0:
$actions .= "<a href='exercise_show.php?".api_get_cidreq()."&action=qualify&id=$id'>".
@ -2234,10 +2233,8 @@ HOTSPOT;
null,
date_default_timezone_get()
);
$hp_result = round(
($hpresults[$i][4] / ($hpresults[$i][5] != 0 ? $hpresults[$i][5] : 1)) * 100,
2
).'% ('.$hpresults[$i][4].' / '.$hpresults[$i][5].')';
$hp_result = round(($hpresults[$i][4] / ($hpresults[$i][5] != 0 ? $hpresults[$i][5] : 1)) * 100, 2)
.'% ('.$hpresults[$i][4].' / '.$hpresults[$i][5].')';
if ($is_allowedToEdit) {
$list_info[] = array(
$hpresults[$i][0],
@ -2329,7 +2326,7 @@ HOTSPOT;
* @param string $pass_percentage
* @return bool
*/
public static function is_success_exercise_result($score, $weight, $pass_percentage)
public static function isSuccessExerciseResult($score, $weight, $pass_percentage)
{
$percentage = float_format(
($score / ($weight != 0 ? $weight : 1)) * 100,
@ -2349,17 +2346,17 @@ HOTSPOT;
* @param string $pass_percentage
* @return string
*/
public static function show_success_message($score, $weight, $pass_percentage)
public static function showSuccessMessage($score, $weight, $pass_percentage)
{
$res = '';
if (self::isPassPercentageEnabled($pass_percentage)) {
$is_success = self::is_success_exercise_result(
$isSuccess = self::isSuccessExerciseResult(
$score,
$weight,
$pass_percentage
);
if ($is_success) {
if ($isSuccess) {
$html = get_lang('CongratulationsYouPassedTheTest');
$icon = Display::return_icon(
'completed.png',
@ -2463,8 +2460,7 @@ HOTSPOT;
$search = '',
$search_all_sessions = false,
$active = 2
)
{
) {
$course_id = api_get_course_int_id();
if (!empty($course_info) && !empty($course_info['real_id'])) {
@ -2549,9 +2545,9 @@ HOTSPOT;
* @param int $courseId The course ID (necessary as c_quiz.id is not unique)
* @return array Exercise info
*/
public static function get_exercise_by_id($exerciseId = 0, $courseId = null)
public static function get_exercise_by_id($exerciseId = 0, $courseId = 0)
{
$TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST);
$table = Database::get_course_table(TABLE_QUIZ_TEST);
if (empty($courseId)) {
$courseId = api_get_course_int_id();
} else {
@ -2564,7 +2560,7 @@ HOTSPOT;
)
);
return Database::select('*', $TBL_EXERCICES, $conditions);
return Database::select('*', $table, $conditions);
}
/**
@ -3758,7 +3754,6 @@ HOTSPOT;
$question_list_answers = array();
$media_list = array();
$category_list = array();
$loadChoiceFromSession = false;
$fromDatabase = true;
$exerciseResult = null;
@ -3773,6 +3768,7 @@ HOTSPOT;
$delineationResults = isset($delineationResults[$objExercise->id]) ? $delineationResults[$objExercise->id] : null;
}
$countPendingQuestions = 0;
// Loop over all question to show results for each of them, one by one
if (!empty($question_list)) {
foreach ($question_list as $questionId) {
@ -3865,7 +3861,7 @@ HOTSPOT;
$comnt = Event::get_comments($exe_id, $questionId);
if (!empty($comnt)) {
echo '<b>'.get_lang('Feedback').'</b>';
echo '<div id="question_feedback">'.$comnt.'</div>';
echo ExerciseLib::getFeedbackText($comnt);
}
}
@ -3886,6 +3882,13 @@ HOTSPOT;
$score = array();
}
if (in_array($objQuestionTmp->type, [FREE_ANSWER, ORAL_EXPRESSION])) {
$check = $objQuestionTmp->isQuestionWaitingReview($score);
if ($check === false) {
$countPendingQuestions++;
}
}
$contents = ob_get_clean();
$question_content = '';
if ($show_results) {
@ -3910,11 +3913,12 @@ HOTSPOT;
$total_score_text = null;
if ($show_results || $show_only_score) {
$total_score_text .= '<div class="question_row_score">';
$total_score_text .= self::get_question_ribbon(
$total_score_text .= self::getTotalScoreRibbon(
$objExercise,
$total_score,
$total_weight,
true
true,
$countPendingQuestions
);
$total_score_text .= '</div>';
}
@ -3995,39 +3999,57 @@ HOTSPOT;
}
}
/**
* @param string $class
* @param string $scoreLabel
* @param string $result
*
* @return string
*/
public static function getQuestionRibbon($class, $scoreLabel, $result)
{
return '<div class="ribbon">
<div class="rib rib-'.$class.'">
<h3>'.$scoreLabel.'</h3>
</div>
<h4>'.get_lang('Score').': '.$result.'</h4>
</div>'
;
}
/**
* @param Exercise $objExercise
* @param float $score
* @param float $weight
* @param bool $check_pass_percentage
* @param bool $checkPassPercentage
* @param int $countPendingQuestions
* @return string
*/
public static function get_question_ribbon(
public static function getTotalScoreRibbon(
$objExercise,
$score,
$weight,
$check_pass_percentage = false
$checkPassPercentage = false,
$countPendingQuestions = 0
) {
$passPercentage = $objExercise->selectPassPercentage();
$ribbon = '<div class="title-score">';
if ($check_pass_percentage) {
$is_success = self::is_success_exercise_result(
if ($checkPassPercentage) {
$isSuccess = self::isSuccessExerciseResult(
$score,
$weight,
$objExercise->selectPassPercentage()
$passPercentage
);
// Color the final test score if pass_percentage activated
$ribbon_total_success_or_error = '';
if (self::isPassPercentageEnabled(
$objExercise->selectPassPercentage()
)
) {
if ($is_success) {
$ribbon_total_success_or_error = ' ribbon-total-success';
$class = '';
if (self::isPassPercentageEnabled($passPercentage)) {
if ($isSuccess) {
$class = ' ribbon-total-success';
} else {
$ribbon_total_success_or_error = ' ribbon-total-error';
$class = ' ribbon-total-error';
}
}
$ribbon .= '<div class="total '.$ribbon_total_success_or_error.'">';
$ribbon .= '<div class="total '.$class.'">';
} else {
$ribbon .= '<div class="total">';
}
@ -4035,15 +4057,26 @@ HOTSPOT;
$ribbon .= self::show_score($score, $weight, false, true);
$ribbon .= '</h3>';
$ribbon .= '</div>';
if ($check_pass_percentage) {
$ribbon .= self::show_success_message(
if ($checkPassPercentage) {
$ribbon .= self::showSuccessMessage(
$score,
$weight,
$objExercise->selectPassPercentage()
$passPercentage
);
}
$ribbon .= '</div>';
if (!empty($countPendingQuestions)) {
$ribbon .= '<br />';
$ribbon .= Display::return_message(
sprintf(
get_lang('TempScoreXQuestionsNotCorrectedYet'),
$countPendingQuestions
),
'warning'
);
}
return $ribbon;
}
@ -4101,4 +4134,23 @@ HOTSPOT;
return $message;
}
/**
* @return string
*/
public static function getNotCorrectedYetText()
{
return Display::return_message(get_lang('notCorrectedYet'), 'warning');
}
/**
* @param string $message
* @return string
*/
public static function getFeedbackText($message)
{
// Old style
//return '<div id="question_feedback">'.$message.'</div>';
return Display::return_message($message, 'warning', false);
}
}

@ -133,7 +133,7 @@ class ExerciseShowFunctions
if ($questionScore > 0 || !empty($comments)) {
} else {
echo '<tr>';
echo Display::tag('td', Display::return_message(get_lang('notCorrectedYet')), array());
echo Display::tag('td', ExerciseLib::getNotCorrectedYetText(), []);
echo '</tr>';
}
}
@ -163,7 +163,7 @@ class ExerciseShowFunctions
echo '</tr>';
if ($feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM) {
echo '<tr>';
echo Display::tag('td', get_lang('notCorrectedYet'), array('width'=>'45%'));
echo Display::tag('td', ExerciseLib::getNotCorrectedYetText(), array('width'=>'45%'));
echo '</tr>';
} else {
echo '<tr><td>&nbsp;</td></tr>';
@ -194,6 +194,7 @@ class ExerciseShowFunctions
* @param string $answerComment
* @param int $resultsDisabled
* @param int $orderColor
* @param bool $showTotalScoreAndUserChoices
*/
public static function display_hotspot_answer(
$feedback_type,
@ -529,8 +530,7 @@ class ExerciseShowFunctions
} else {
echo $question->options[2];
}
}
else {
} else {
echo '-';
}
?>
@ -541,8 +541,8 @@ class ExerciseShowFunctions
echo $answer;
?>
</td>
<?php if ($feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM) { ?>
<?php
if ($feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM) { ?>
<td width="20%">
<?php
//@todo replace this harcoded value
@ -551,7 +551,6 @@ class ExerciseShowFunctions
if ($studentChoice == $answerCorrect) {
$color = "green";
}
//echo '<span style="font-weight: bold; color: #000;">'.nl2br($answerComment).'</span>';
if ($hide_expected_answer) {
$color = '';
}
@ -563,14 +562,19 @@ class ExerciseShowFunctions
if ($ans == 1) {
$comm = Event::get_comments($id, $questionId);
}
?>
<?php } else { ?>
<td>&nbsp;</td>
<?php } ?>
</tr>
<?php
} else {
echo '<td>&nbsp;</td>';
}
echo '</tr>';
}
/**
* @param $feedback_type
* @param $exe_id
* @param $questionId
* @param null $questionScore
* @param int $results_disabled
*/
public static function displayAnnotationAnswer(
$feedback_type,
$exe_id,
@ -579,10 +583,9 @@ class ExerciseShowFunctions
$results_disabled = 0
) {
$comments = Event::get_comments($exe_id, $questionId);
if ($feedback_type != EXERCISE_FEEDBACK_TYPE_EXAM) {
if ($questionScore <= 0 && empty($comments)) {
echo '<br>'.Display::return_message(get_lang('notCorrectedYet'));
echo '<br />'.ExerciseLib::getNotCorrectedYetText();
}
}
}

@ -8014,4 +8014,5 @@ $SendEmailToTeacherWhenStudentEndQuiz = "Send email to teacher when student ends
$SendEmailToTeacherWhenStudentEndQuizOnlyIfOpenQuestion = "Send email to teacher when student ends an exercise only if an open question is answered.";
$SendEmailToTeacherWhenStudentEndQuizOnlyIfOralQuestion = "Send email to teacher when student ends an exercise only if an oral question is answered.";
$StudentStartExercise = "Student just started an exercise";
$TempScoreXQuestionsNotCorrectedYet = 'Temporary score: %s open question(s) not corrected yet.';
?>

@ -303,7 +303,7 @@ if (!empty($_REQUEST['exeId']) &&
if (!empty($exercise->pass_percentage)) {
$status = 'failed';
$success = ExerciseLib::is_success_exercise_result(
$success = ExerciseLib::isSuccessExerciseResult(
$score,
$max_score,
$exercise->pass_percentage
@ -322,7 +322,6 @@ if (!empty($_REQUEST['exeId']) &&
if ($debug) {
error_log($sql);
}
Database::query($sql);
$sql = "UPDATE $TBL_TRACK_EXERCICES SET

Loading…
Cancel
Save