|
@@ -2834,7 +2834,7 @@ class Exercise
|
|
|
|
|
|
// if we want to delete results from LP too
|
|
|
if ($cleanLpTests) {
|
|
|
- $sql_where = "";
|
|
|
+ $sql_where = '';
|
|
|
}
|
|
|
|
|
|
// if we want to delete attempts before date $cleanResultBeforeDate
|
|
@@ -2850,12 +2850,12 @@ class Exercise
|
|
|
}
|
|
|
|
|
|
$sql = "SELECT exe_id
|
|
|
- FROM $table_track_e_exercises
|
|
|
- WHERE
|
|
|
- c_id = ".api_get_course_int_id()." AND
|
|
|
- exe_exo_id = ".$this->id." AND
|
|
|
- session_id = ".api_get_session_id()." ".
|
|
|
- $sql_where;
|
|
|
+ FROM $table_track_e_exercises
|
|
|
+ WHERE
|
|
|
+ c_id = ".api_get_course_int_id()." AND
|
|
|
+ exe_exo_id = ".$this->id." AND
|
|
|
+ session_id = ".api_get_session_id()." ".
|
|
|
+ $sql_where;
|
|
|
|
|
|
$result = Database::query($sql);
|
|
|
$exe_list = Database::store_result($result);
|
|
@@ -2875,10 +2875,10 @@ class Exercise
|
|
|
$session_id = api_get_session_id();
|
|
|
// delete TRACK_E_EXERCISES table
|
|
|
$sql = "DELETE FROM $table_track_e_exercises
|
|
|
- WHERE c_id = ".api_get_course_int_id()."
|
|
|
- AND exe_exo_id = ".$this->id."
|
|
|
- $sql_where
|
|
|
- AND session_id = ".$session_id;
|
|
|
+ WHERE
|
|
|
+ c_id = ".api_get_course_int_id()." AND
|
|
|
+ exe_exo_id = ".$this->id." $sql_where AND
|
|
|
+ session_id = ".$session_id;
|
|
|
Database::query($sql);
|
|
|
|
|
|
Event::addEvent(
|
|
@@ -3232,26 +3232,7 @@ class Exercise
|
|
|
$time_left = intval($time_left);
|
|
|
|
|
|
return "<script>
|
|
|
-
|
|
|
- function get_expired_date_string(expired_time) {
|
|
|
- var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
|
- var day, month, year, hours, minutes, seconds, date_string;
|
|
|
- var obj_date = new Date(expired_time);
|
|
|
- day = obj_date.getDate();
|
|
|
- if (day < 10) day = '0' + day;
|
|
|
- month = obj_date.getMonth();
|
|
|
- year = obj_date.getFullYear();
|
|
|
- hours = obj_date.getHours();
|
|
|
- if (hours < 10) hours = '0' + hours;
|
|
|
- minutes = obj_date.getMinutes();
|
|
|
- if (minutes < 10) minutes = '0' + minutes;
|
|
|
- seconds = obj_date.getSeconds();
|
|
|
- if (seconds < 10) seconds = '0' + seconds;
|
|
|
- date_string = months[month] +' ' + day + ', ' + year + ' ' + hours + ':' + minutes + ':' + seconds;
|
|
|
- return date_string;
|
|
|
- }
|
|
|
-
|
|
|
- function open_clock_warning() {
|
|
|
+ function openClockWarning() {
|
|
|
$('#clock_warning').dialog({
|
|
|
modal:true,
|
|
|
height:250,
|
|
@@ -3267,7 +3248,6 @@ class Exercise
|
|
|
}
|
|
|
});
|
|
|
$('#clock_warning').dialog('open');
|
|
|
-
|
|
|
$('#counter_to_redirect').epiclock({
|
|
|
mode: $.epiclock.modes.countdown,
|
|
|
offset: {seconds: 5},
|
|
@@ -3279,7 +3259,7 @@ class Exercise
|
|
|
|
|
|
function send_form() {
|
|
|
if ($('#exercise_form').length) {
|
|
|
- $('#exercise_form').submit();
|
|
|
+ save_now_all('validate');
|
|
|
} else {
|
|
|
// In exercise_reminder.php
|
|
|
final_submit();
|
|
@@ -3288,21 +3268,15 @@ class Exercise
|
|
|
|
|
|
function onExpiredTimeExercise() {
|
|
|
$('#wrapper-clock').hide();
|
|
|
- //$('#exercise_form').hide();
|
|
|
$('#expired-message-id').show();
|
|
|
-
|
|
|
//Fixes bug #5263
|
|
|
$('#num_current_id').attr('value', '".$this->selectNbrQuestions()."');
|
|
|
- open_clock_warning();
|
|
|
+ openClockWarning();
|
|
|
}
|
|
|
|
|
|
$(document).ready(function() {
|
|
|
- var current_time = new Date().getTime();
|
|
|
// time in seconds when using minutes there are some seconds lost
|
|
|
- var time_left = parseInt(".$time_left.");
|
|
|
- var expired_time = current_time + (time_left*1000);
|
|
|
- var expired_date = get_expired_date_string(expired_time);
|
|
|
-
|
|
|
+ var time_left = parseInt(".$time_left.");
|
|
|
$('#exercise_clock_warning').epiclock({
|
|
|
mode: $.epiclock.modes.countdown,
|
|
|
offset: {seconds: time_left},
|
|
@@ -3321,7 +3295,7 @@ class Exercise
|
|
|
*
|
|
|
* @param int $exeId
|
|
|
* @param int $questionId
|
|
|
- * @param int $choice the user selected
|
|
|
+ * @param mixed $choice the user-selected option
|
|
|
* @param string $from function is called from 'exercise_show' or 'exercise_result'
|
|
|
* @param array $exerciseResultCoordinates the hotspot coordinates $hotspot[$question_id] = coordinates
|
|
|
* @param bool $saved_results save results in the DB or just show the reponse
|
|
@@ -3382,8 +3356,12 @@ class Exercise
|
|
|
$threadhold3 = 0;
|
|
|
$arrques = null;
|
|
|
$arrans = null;
|
|
|
- $questionId = intval($questionId);
|
|
|
- $exeId = intval($exeId);
|
|
|
+ $studentChoice = null;
|
|
|
+ $expectedAnswer = '';
|
|
|
+ $calculatedChoice = '';
|
|
|
+ $calculatedStatus = '';
|
|
|
+ $questionId = (int) $questionId;
|
|
|
+ $exeId = (int) $exeId;
|
|
|
$TBL_TRACK_ATTEMPT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
|
|
|
$table_ans = Database::get_course_table(TABLE_QUIZ_ANSWER);
|
|
|
|
|
@@ -3405,12 +3383,18 @@ class Exercise
|
|
|
$totalScore = 0;
|
|
|
|
|
|
// Extra information of the question
|
|
|
- if ($answerType == MULTIPLE_ANSWER_TRUE_FALSE && !empty($extra)) {
|
|
|
+ if ((
|
|
|
+ $answerType == MULTIPLE_ANSWER_TRUE_FALSE ||
|
|
|
+ $answerType == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY
|
|
|
+ )
|
|
|
+ && !empty($extra)
|
|
|
+ ) {
|
|
|
$extra = explode(':', $extra);
|
|
|
if ($debug) {
|
|
|
error_log(print_r($extra, 1));
|
|
|
}
|
|
|
// Fixes problems with negatives values using intval
|
|
|
+
|
|
|
$true_score = floatval(trim($extra[0]));
|
|
|
$false_score = floatval(trim($extra[1]));
|
|
|
$doubt_score = floatval(trim($extra[2]));
|
|
@@ -3425,6 +3409,12 @@ class Exercise
|
|
|
error_log('$answerType: '.$answerType);
|
|
|
}
|
|
|
|
|
|
+ if ($answerType == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) {
|
|
|
+ $choiceTmp = $choice;
|
|
|
+ $choice = $choiceTmp["choice"];
|
|
|
+ $choiceDegreeCertainty = $choiceTmp["choiceDegreeCertainty"];
|
|
|
+ }
|
|
|
+
|
|
|
if ($answerType == FREE_ANSWER ||
|
|
|
$answerType == ORAL_EXPRESSION ||
|
|
|
$answerType == CALCULATED_ANSWER ||
|
|
@@ -3508,7 +3498,6 @@ class Exercise
|
|
|
$answer_delineation_destination = $objAnswerTmp->selectDestination(1);
|
|
|
|
|
|
switch ($answerType) {
|
|
|
- // for unique answer
|
|
|
case UNIQUE_ANSWER:
|
|
|
case UNIQUE_ANSWER_IMAGE:
|
|
|
case UNIQUE_ANSWER_NO_OPTION:
|
|
@@ -3534,7 +3523,6 @@ class Exercise
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
- // for multiple answers
|
|
|
case MULTIPLE_ANSWER_TRUE_FALSE:
|
|
|
if ($from_database) {
|
|
|
$choice = [];
|
|
@@ -3572,6 +3560,55 @@ class Exercise
|
|
|
}
|
|
|
$totalScore = $questionScore;
|
|
|
break;
|
|
|
+ case MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY:
|
|
|
+ if ($from_database) {
|
|
|
+ $choice = [];
|
|
|
+ $choiceDegreeCertainty = [];
|
|
|
+ $sql = "SELECT answer
|
|
|
+ FROM $TBL_TRACK_ATTEMPT
|
|
|
+ WHERE
|
|
|
+ exe_id = $exeId AND question_id = $questionId";
|
|
|
+
|
|
|
+ $result = Database::query($sql);
|
|
|
+ while ($row = Database::fetch_array($result)) {
|
|
|
+ $ind = $row['answer'];
|
|
|
+ $values = explode(':', $ind);
|
|
|
+ $myAnswerId = $values[0];
|
|
|
+ $option = $values[1];
|
|
|
+ $percent = $values[2];
|
|
|
+ $choice[$myAnswerId] = $option;
|
|
|
+ $choiceDegreeCertainty[$myAnswerId] = $percent;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null;
|
|
|
+ $studentChoiceDegree = isset($choiceDegreeCertainty[$answerAutoId]) ?
|
|
|
+ $choiceDegreeCertainty[$answerAutoId] : null;
|
|
|
+
|
|
|
+ // student score update
|
|
|
+ if (!empty($studentChoice)) {
|
|
|
+ if ($studentChoice == $answerCorrect) {
|
|
|
+ // correct answer and student is Unsure or PrettySur
|
|
|
+ if ($quiz_question_options[$studentChoiceDegree]['position'] >= 3
|
|
|
+ && $quiz_question_options[$studentChoiceDegree]['position'] < 9) {
|
|
|
+ $questionScore += $true_score;
|
|
|
+ } else {
|
|
|
+ // student ignore correct answer
|
|
|
+ $questionScore += $doubt_score;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // false answer and student is Unsure or PrettySur
|
|
|
+ if ($quiz_question_options[$studentChoiceDegree]['position'] >= 3
|
|
|
+ && $quiz_question_options[$studentChoiceDegree]['position'] < 9) {
|
|
|
+ $questionScore += $false_score;
|
|
|
+ } else {
|
|
|
+ // student ignore correct answer
|
|
|
+ $questionScore += $doubt_score;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $totalScore = $questionScore;
|
|
|
+ break;
|
|
|
case MULTIPLE_ANSWER: //2
|
|
|
if ($from_database) {
|
|
|
$choice = [];
|
|
@@ -3797,6 +3834,7 @@ class Exercise
|
|
|
$answer = '';
|
|
|
$real_correct_tags = $correct_tags;
|
|
|
$chosen_list = [];
|
|
|
+
|
|
|
for ($i = 0; $i < count($real_correct_tags); $i++) {
|
|
|
if ($i == 0) {
|
|
|
$answer .= $real_text[0];
|
|
@@ -3852,10 +3890,7 @@ class Exercise
|
|
|
// 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
|
|
|
- );
|
|
|
-
|
|
|
+ $listCorrectAnswers = FillBlanks::getAnswerInfo($answer);
|
|
|
$switchableAnswerSet = $listCorrectAnswers['switchable'];
|
|
|
$answerWeighting = $listCorrectAnswers['weighting'];
|
|
|
// user choices is an array $choice
|
|
@@ -3919,7 +3954,6 @@ class Exercise
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
$listCorrectAnswers['student_answer'][$i] = $studentAnswerToShow;
|
|
|
$listCorrectAnswers['student_score'][$i] = $isAnswerCorrect;
|
|
|
}
|
|
@@ -3976,9 +4010,7 @@ class Exercise
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- $answer = FillBlanks::getAnswerInStudentAttempt(
|
|
|
- $listCorrectAnswers
|
|
|
- );
|
|
|
+ $answer = FillBlanks::getAnswerInStudentAttempt($listCorrectAnswers);
|
|
|
}
|
|
|
break;
|
|
|
case CALCULATED_ANSWER:
|
|
@@ -4027,7 +4059,6 @@ class Exercise
|
|
|
question_id = ".intval($questionId);
|
|
|
$result = Database::query($sql);
|
|
|
$str = Database::result($result, 0, 'answer');
|
|
|
-
|
|
|
api_preg_match_all('#\[([^[]*)\]#', $str, $arr);
|
|
|
$str = str_replace('\r\n', '', $str);
|
|
|
$choice = $arr[1];
|
|
@@ -4499,9 +4530,9 @@ class Exercise
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
- // @todo never added to chamilo
|
|
|
- //for hotspot with fixed order
|
|
|
case HOT_SPOT_ORDER:
|
|
|
+ // @todo never added to chamilo
|
|
|
+ // for hotspot with fixed order
|
|
|
$studentChoice = $choice['order'][$answerId];
|
|
|
if ($studentChoice == $answerId) {
|
|
|
$questionScore += $answerWeighting;
|
|
@@ -4511,8 +4542,8 @@ class Exercise
|
|
|
$studentChoice = false;
|
|
|
}
|
|
|
break;
|
|
|
- // for hotspot with delineation
|
|
|
case HOT_SPOT_DELINEATION:
|
|
|
+ // for hotspot with delineation
|
|
|
if ($from_database) {
|
|
|
// getting the user answer
|
|
|
$TBL_TRACK_HOTSPOT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
|
|
@@ -4558,9 +4589,9 @@ class Exercise
|
|
|
case ANNOTATION:
|
|
|
if ($from_database) {
|
|
|
$sql = "SELECT answer, marks FROM $TBL_TRACK_ATTEMPT
|
|
|
- WHERE
|
|
|
- exe_id = $exeId AND
|
|
|
- question_id= ".$questionId;
|
|
|
+ WHERE
|
|
|
+ exe_id = $exeId AND
|
|
|
+ question_id= ".$questionId;
|
|
|
$resq = Database::query($sql);
|
|
|
$data = Database::fetch_array($resq);
|
|
|
|
|
@@ -4570,9 +4601,7 @@ class Exercise
|
|
|
$arrques = $questionName;
|
|
|
break;
|
|
|
}
|
|
|
-
|
|
|
$studentChoice = $choice;
|
|
|
-
|
|
|
if ($studentChoice) {
|
|
|
$questionScore = 0;
|
|
|
$totalScore += 0;
|
|
@@ -4631,6 +4660,17 @@ class Exercise
|
|
|
$results_disabled,
|
|
|
$showTotalScoreAndUserChoicesInLastAttempt
|
|
|
);
|
|
|
+ } elseif ($answerType == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) {
|
|
|
+ ExerciseShowFunctions::displayMultipleAnswerTrueFalseDegreeCertainty(
|
|
|
+ $feedback_type,
|
|
|
+ $studentChoice,
|
|
|
+ $studentChoiceDegree,
|
|
|
+ $answer,
|
|
|
+ $answerComment,
|
|
|
+ $answerCorrect,
|
|
|
+ $questionId,
|
|
|
+ $results_disabled
|
|
|
+ );
|
|
|
} elseif ($answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) {
|
|
|
ExerciseShowFunctions::display_multiple_answer_combination_true_false(
|
|
|
$this,
|
|
@@ -5012,6 +5052,31 @@ class Exercise
|
|
|
);
|
|
|
}
|
|
|
break;
|
|
|
+ case MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY:
|
|
|
+ if ($answerId == 1) {
|
|
|
+ ExerciseShowFunctions::displayMultipleAnswerTrueFalseDegreeCertainty(
|
|
|
+ $feedback_type,
|
|
|
+ $studentChoice,
|
|
|
+ $studentChoiceDegree,
|
|
|
+ $answer,
|
|
|
+ $answerComment,
|
|
|
+ $answerCorrect,
|
|
|
+ $questionId,
|
|
|
+ $results_disabled
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ ExerciseShowFunctions::displayMultipleAnswerTrueFalseDegreeCertainty(
|
|
|
+ $feedback_type,
|
|
|
+ $studentChoice,
|
|
|
+ $studentChoiceDegree,
|
|
|
+ $answer,
|
|
|
+ $answerComment,
|
|
|
+ $answerCorrect,
|
|
|
+ $questionId,
|
|
|
+ $results_disabled
|
|
|
+ );
|
|
|
+ }
|
|
|
+ break;
|
|
|
case FILL_IN_BLANKS:
|
|
|
ExerciseShowFunctions::display_fill_in_blanks_answer(
|
|
|
$feedback_type,
|
|
@@ -5388,19 +5453,19 @@ class Exercise
|
|
|
<td><b>'.get_lang('Overlap').'</b></td>
|
|
|
<td>'.get_lang('Min').' '.$threadhold1.'</td>
|
|
|
<td><div style="color:'.$overlap_color.'">'
|
|
|
- .(($final_overlap < 0) ? 0 : intval($final_overlap)).'</div></td>
|
|
|
+ .(($final_overlap < 0) ? 0 : intval($final_overlap)).'</div></td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td><b>'.get_lang('Excess').'</b></td>
|
|
|
<td>'.get_lang('Max').' '.$threadhold2.'</td>
|
|
|
<td><div style="color:'.$excess_color.'">'
|
|
|
- .(($final_excess < 0) ? 0 : intval($final_excess)).'</div></td>
|
|
|
+ .(($final_excess < 0) ? 0 : intval($final_excess)).'</div></td>
|
|
|
</tr>
|
|
|
<tr class="row_even">
|
|
|
<td><b>'.get_lang('Missing').'</b></td>
|
|
|
<td>'.get_lang('Max').' '.$threadhold3.'</td>
|
|
|
<td><div style="color:'.$missing_color.'">'
|
|
|
- .(($final_missing < 0) ? 0 : intval($final_missing)).'</div></td>
|
|
|
+ .(($final_missing < 0) ? 0 : intval($final_missing)).'</div></td>
|
|
|
</tr>
|
|
|
</table>';
|
|
|
if ($next == 0) {
|
|
@@ -5529,9 +5594,11 @@ class Exercise
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ //if ($origin != 'learnpath') {
|
|
|
if ($show_result && $answerType != ANNOTATION) {
|
|
|
echo '</table>';
|
|
|
}
|
|
|
+ // }
|
|
|
}
|
|
|
unset($objAnswerTmp);
|
|
|
|
|
@@ -5542,29 +5609,51 @@ class Exercise
|
|
|
if ($saved_results) {
|
|
|
if ($debug) {
|
|
|
error_log("Save question results $saved_results");
|
|
|
- }
|
|
|
- if ($debug) {
|
|
|
+ error_log('choice: ');
|
|
|
error_log(print_r($choice, 1));
|
|
|
}
|
|
|
|
|
|
if (empty($choice)) {
|
|
|
$choice = 0;
|
|
|
}
|
|
|
- if ($answerType == MULTIPLE_ANSWER_TRUE_FALSE || $answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) {
|
|
|
+ // with certainty degree
|
|
|
+ if (empty($choiceDegreeCertainty)) {
|
|
|
+ $choiceDegreeCertainty = 0;
|
|
|
+ }
|
|
|
+ if ($answerType == MULTIPLE_ANSWER_TRUE_FALSE ||
|
|
|
+ $answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE ||
|
|
|
+ $answerType == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY
|
|
|
+ ) {
|
|
|
if ($choice != 0) {
|
|
|
$reply = array_keys($choice);
|
|
|
for ($i = 0; $i < sizeof($reply); $i++) {
|
|
|
- $ans = $reply[$i];
|
|
|
- Event::saveQuestionAttempt(
|
|
|
- $questionScore,
|
|
|
- $ans.':'.$choice[$ans],
|
|
|
- $quesId,
|
|
|
- $exeId,
|
|
|
- $i,
|
|
|
- $this->id
|
|
|
- );
|
|
|
+ $chosenAnswer = $reply[$i];
|
|
|
+ if ($answerType == MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY) {
|
|
|
+ if ($choiceDegreeCertainty != 0) {
|
|
|
+ $replyDegreeCertainty = array_keys($choiceDegreeCertainty);
|
|
|
+ $answerDegreeCertainty = $replyDegreeCertainty[$i];
|
|
|
+ Event::saveQuestionAttempt(
|
|
|
+ $questionScore,
|
|
|
+ $chosenAnswer.':'.$choice[$chosenAnswer].':'.
|
|
|
+ $choiceDegreeCertainty[$answerDegreeCertainty],
|
|
|
+ $quesId,
|
|
|
+ $exeId,
|
|
|
+ $i,
|
|
|
+ $this->id
|
|
|
+ );
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Event::saveQuestionAttempt(
|
|
|
+ $questionScore,
|
|
|
+ $chosenAnswer.':'.$choice[$chosenAnswer],
|
|
|
+ $quesId,
|
|
|
+ $exeId,
|
|
|
+ $i,
|
|
|
+ $this->id
|
|
|
+ );
|
|
|
+ }
|
|
|
if ($debug) {
|
|
|
- error_log('result =>'.$questionScore.' '.$ans.':'.$choice[$ans]);
|
|
|
+ error_log('result =>'.$questionScore.' '.$chosenAnswer.':'.$choice[$chosenAnswer]);
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
@@ -5651,10 +5740,12 @@ class Exercise
|
|
|
) {
|
|
|
$answer = $choice;
|
|
|
Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id);
|
|
|
- // } elseif ($answerType == HOT_SPOT || $answerType == HOT_SPOT_DELINEATION) {
|
|
|
} elseif ($answerType == HOT_SPOT || $answerType == ANNOTATION) {
|
|
|
$answer = [];
|
|
|
if (isset($exerciseResultCoordinates[$questionId]) && !empty($exerciseResultCoordinates[$questionId])) {
|
|
|
+ if ($debug) {
|
|
|
+ error_log('Checking result coordinates');
|
|
|
+ }
|
|
|
Database::delete(
|
|
|
Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT),
|
|
|
[
|
|
@@ -5669,6 +5760,9 @@ class Exercise
|
|
|
foreach ($exerciseResultCoordinates[$questionId] as $idx => $val) {
|
|
|
$answer[] = $val;
|
|
|
$hotspotValue = (int) $choice[$idx] === 1 ? 1 : 0;
|
|
|
+ if ($debug) {
|
|
|
+ error_log('Hotspot value: '.$hotspotValue);
|
|
|
+ }
|
|
|
Event::saveExerciseAttemptHotspot(
|
|
|
$exeId,
|
|
|
$quesId,
|
|
@@ -5679,6 +5773,10 @@ class Exercise
|
|
|
$this->id
|
|
|
);
|
|
|
}
|
|
|
+ } else {
|
|
|
+ if ($debug) {
|
|
|
+ error_log("Empty: exerciseResultCoordinates");
|
|
|
+ }
|
|
|
}
|
|
|
Event::saveQuestionAttempt($questionScore, implode('|', $answer), $quesId, $exeId, 0, $this->id);
|
|
|
} else {
|
|
@@ -5691,14 +5789,17 @@ class Exercise
|
|
|
}
|
|
|
|
|
|
if ($saved_results) {
|
|
|
- $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
|
|
|
- $sql = 'UPDATE '.$table.' SET
|
|
|
- exe_result = exe_result + '.floatval($questionScore).'
|
|
|
- WHERE exe_id = '.$exeId;
|
|
|
+ $statsTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
|
|
|
+ $sql = "UPDATE $statsTable SET
|
|
|
+ exe_result = exe_result + ".floatval($questionScore)."
|
|
|
+ WHERE exe_id = $exeId";
|
|
|
Database::query($sql);
|
|
|
+ if ($debug) {
|
|
|
+ error_log($sql);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- $return = [
|
|
|
+ $return_array = [
|
|
|
'score' => $questionScore,
|
|
|
'weight' => $questionWeighting,
|
|
|
'extra' => $extra_data,
|
|
@@ -5708,7 +5809,7 @@ class Exercise
|
|
|
'generated_oral_file' => $generatedFile,
|
|
|
];
|
|
|
|
|
|
- return $return;
|
|
|
+ return $return_array;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -5785,7 +5886,8 @@ class Exercise
|
|
|
}
|
|
|
|
|
|
$user_info = api_get_user_info(api_get_user_id());
|
|
|
- $url = api_get_path(WEB_CODE_PATH).'exercise/exercise_show.php?'.api_get_cidreq().'&id='.$exe_id.'&action=qualify';
|
|
|
+ $url = api_get_path(WEB_CODE_PATH).'exercise/exercise_show.php?'.
|
|
|
+ api_get_cidreq(true, true, 'qualify').'&id='.$exe_id.'&action=qualify';
|
|
|
|
|
|
if (!empty($sessionId)) {
|
|
|
$addGeneralCoach = true;
|
|
@@ -5873,12 +5975,13 @@ class Exercise
|
|
|
'#student_complete_name#' => $user_info['complete_name'],
|
|
|
'#course#' => $courseInfo['title'],
|
|
|
];
|
|
|
- if ($origin != 'learnpath' && $sendEnd) {
|
|
|
+
|
|
|
+ if ($sendEnd) {
|
|
|
$msg .= '<br /><a href="#url#">'.get_lang('ClickToCommentAndGiveFeedback').'</a>';
|
|
|
$variables['#url#'] = $url;
|
|
|
}
|
|
|
|
|
|
- $mail_content = str_replace(array_keys($variables), array_values($variables), $msg);
|
|
|
+ $content = str_replace(array_keys($variables), array_values($variables), $msg);
|
|
|
|
|
|
if ($sendEnd) {
|
|
|
$subject = get_lang('ExerciseAttempted');
|
|
@@ -5891,7 +5994,7 @@ class Exercise
|
|
|
MessageManager::send_message_simple(
|
|
|
$user_id,
|
|
|
$subject,
|
|
|
- $mail_content
|
|
|
+ $content
|
|
|
);
|
|
|
}
|
|
|
}
|
|
@@ -5916,9 +6019,13 @@ class Exercise
|
|
|
|
|
|
$array = [];
|
|
|
if (!empty($user_data)) {
|
|
|
+ $userFullName = $user_data['complete_name'];
|
|
|
+ if (api_is_teacher() || api_is_platform_admin(true, true)) {
|
|
|
+ $userFullName = '<a href="'.$user_data['profile_url'].'" title="'.get_lang('GoToStudentDetails').'">'.$user_data['complete_name'].'</a>';
|
|
|
+ }
|
|
|
$array[] = [
|
|
|
'title' => get_lang('Name'),
|
|
|
- 'content' => $user_data['complete_name'],
|
|
|
+ 'content' => $userFullName,
|
|
|
];
|
|
|
$array[] = [
|
|
|
'title' => get_lang('Username'),
|
|
@@ -7874,6 +7981,16 @@ class Exercise
|
|
|
Database::query($sql);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the title without HTML tags.
|
|
|
+ *
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public function getUnformattedTitle()
|
|
|
+ {
|
|
|
+ return strip_tags(api_html_entity_decode($this->title));
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Gets the question list ordered by the question_order setting (drag and drop).
|
|
|
*
|
|
@@ -8040,25 +8157,25 @@ class Exercise
|
|
|
$courseInfo = api_get_course_info($courseCode);
|
|
|
|
|
|
$msg = get_lang('OpenQuestionsAttempted').'<br /><br />'
|
|
|
- .get_lang('AttemptDetails').' : <br /><br />'
|
|
|
- .'<table>'
|
|
|
- .'<tr>'
|
|
|
- .'<td><em>'.get_lang('CourseName').'</em></td>'
|
|
|
- .'<td> <b>#course#</b></td>'
|
|
|
- .'</tr>'
|
|
|
- .'<tr>'
|
|
|
- .'<td>'.get_lang('TestAttempted').'</td>'
|
|
|
- .'<td> #exercise#</td>'
|
|
|
- .'</tr>'
|
|
|
- .'<tr>'
|
|
|
- .'<td>'.get_lang('StudentName').'</td>'
|
|
|
- .'<td> #firstName# #lastName#</td>'
|
|
|
- .'</tr>'
|
|
|
- .'<tr>'
|
|
|
- .'<td>'.get_lang('StudentEmail').'</td>'
|
|
|
- .'<td> #mail#</td>'
|
|
|
- .'</tr>'
|
|
|
- .'</table>';
|
|
|
+ .get_lang('AttemptDetails').' : <br /><br />'
|
|
|
+ .'<table>'
|
|
|
+ .'<tr>'
|
|
|
+ .'<td><em>'.get_lang('CourseName').'</em></td>'
|
|
|
+ .'<td> <b>#course#</b></td>'
|
|
|
+ .'</tr>'
|
|
|
+ .'<tr>'
|
|
|
+ .'<td>'.get_lang('TestAttempted').'</td>'
|
|
|
+ .'<td> #exercise#</td>'
|
|
|
+ .'</tr>'
|
|
|
+ .'<tr>'
|
|
|
+ .'<td>'.get_lang('StudentName').'</td>'
|
|
|
+ .'<td> #firstName# #lastName#</td>'
|
|
|
+ .'</tr>'
|
|
|
+ .'<tr>'
|
|
|
+ .'<td>'.get_lang('StudentEmail').'</td>'
|
|
|
+ .'<td> #mail#</td>'
|
|
|
+ .'</tr>'
|
|
|
+ .'</table>';
|
|
|
$open_question_list = null;
|
|
|
foreach ($question_list_answers as $item) {
|
|
|
$question = $item['question'];
|
|
@@ -8068,19 +8185,19 @@ class Exercise
|
|
|
if (!empty($question) && !empty($answer) && $answer_type == FREE_ANSWER) {
|
|
|
$open_question_list .=
|
|
|
'<tr>'
|
|
|
- .'<td width="220" valign="top" bgcolor="#E5EDF8"> '.get_lang('Question').'</td>'
|
|
|
- .'<td width="473" valign="top" bgcolor="#F3F3F3">'.$question.'</td>'
|
|
|
+ .'<td width="220" valign="top" bgcolor="#E5EDF8"> '.get_lang('Question').'</td>'
|
|
|
+ .'<td width="473" valign="top" bgcolor="#F3F3F3">'.$question.'</td>'
|
|
|
.'</tr>'
|
|
|
.'<tr>'
|
|
|
- .'<td width="220" valign="top" bgcolor="#E5EDF8"> '.get_lang('Answer').'</td>'
|
|
|
- .'<td valign="top" bgcolor="#F3F3F3">'.$answer.'</td>'
|
|
|
+ .'<td width="220" valign="top" bgcolor="#E5EDF8"> '.get_lang('Answer').'</td>'
|
|
|
+ .'<td valign="top" bgcolor="#F3F3F3">'.$answer.'</td>'
|
|
|
.'</tr>';
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!empty($open_question_list)) {
|
|
|
$msg .= '<p><br />'.get_lang('OpenQuestionsAttemptedAre').' :</p>'.
|
|
|
- '<table width="730" height="136" border="0" cellpadding="3" cellspacing="3">';
|
|
|
+ '<table width="730" height="136" border="0" cellpadding="3" cellspacing="3">';
|
|
|
$msg .= $open_question_list;
|
|
|
$msg .= '</table><br />';
|
|
|
$msg1 = str_replace("#exercise#", $this->exercise, $msg);
|
|
@@ -8237,14 +8354,4 @@ class Exercise
|
|
|
}
|
|
|
$this->mediaList = $mediaList;
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * Get the title without HTML tags.
|
|
|
- *
|
|
|
- * @return string
|
|
|
- */
|
|
|
- private function getUnformattedTitle()
|
|
|
- {
|
|
|
- return strip_tags(api_html_entity_decode($this->title));
|
|
|
- }
|
|
|
}
|