Merge pull request #682 from AngelFQC/7613

Add the type of question Unique Answer Image - refs #7613
1.10.x
Yannick Warnier 11 years ago
commit 6b22bea104
  1. 38
      main/css/base.css
  2. 360
      main/exercice/UniqueAnswerImage.php
  3. 444
      main/exercice/exercise.class.php
  4. 1
      main/exercice/exercise_submit.php
  5. 243
      main/exercice/question.class.php
  6. 2
      main/exercice/question_list_admin.inc.php
  7. 1
      main/inc/lib/api.lib.php
  8. 52
      main/inc/lib/exercise.lib.php
  9. 1
      main/lang/english/trad4all.inc.php
  10. 7
      main/lang/spanish/trad4all.inc.php

@ -5841,3 +5841,41 @@ ul.holder li.bit-box{
border-radius: 50%;
border: 5px solid rgba(0,0,30,0.8);
}
.question_options .exercise-unique-answer-image {
}
@media (min-width: 768px) {
.question_options .exercise-unique-answer-image:nth-child(2n-1) {
clear: both;
}
}
@media (min-width: 992px) {
.question_options .exercise-unique-answer-image:nth-child(2n-1) {
clear: none;
}
.question_options .exercise-unique-answer-image:nth-child(3n-2) {
clear: both;
}
}
.question_options label > input + div.thumbnail {
border-color: transparent;
border-width: 5px;
}
.question_options label > input:checked + div.thumbnail {
border: 5px solid red;
}
.question_options div.thumbnail p {
margin: 0;
}
.question_options div.thumbnail img {
height: auto !important;
max-width: 100%;
}

@ -0,0 +1,360 @@
<?php
/* For licensing terms, see /license.txt */
/**
* UniqueAnswerImage
*
* @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
*/
class UniqueAnswerImage extends UniqueAnswer
{
static $typePicture = 'mcua.png';
static $explanationLangVar = 'UniqueAnswerImage';
public function __construct()
{
//this is highly important
parent::__construct();
$this->type = UNIQUE_ANSWER_IMAGE;
$this->isContent = $this->getIsContent();
}
public function createAnswersForm($form)
{
$objExercise = $_SESSION['objExercise'];
$editorConfig = array(
'ToolbarSet' => 'UniqueAnswerImage',
'Width' => '100%',
'Height' => '125'
);
//this line defines how many questions by default appear when creating a choice question
// The previous default value was 2. See task #1759.
$numberAnswers = isset($_POST['nb_answers']) ? (int) $_POST['nb_answers'] : 4;
$numberAnswers += (isset($_POST['lessAnswers']) ? -1 : (isset($_POST['moreAnswers']) ? 1 : 0));
$feedbackTitle = '';
if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
//Scenario
$commentTitle = '<th>' . get_lang('Comment') . '</th>';
$feedbackTitle = '<th>' . get_lang('Scenario') . '</th>';
} else {
$commentTitle = '<th >' . get_lang('Comment') . '</th>';
}
$html = '<table class="table table-striped table-hover">
<thead>
<tr style="text-align: center;">
<th width="10">' . get_lang('Number') . '</th>
<th>' . get_lang('True') . '</th>
<th>' . get_lang('Answer') . '</th>
' . $commentTitle . '
' . $feedbackTitle . '
<th width="10">' . get_lang('Weighting') . '</th>
</tr>
</thead>
<tbody>';
$form->addHeader(get_lang('Answers'));
$form->addHtml($html);
$defaults = array();
$correct = 0;
if (!empty($this->id)) {
$answer = new Answer($this->id);
$answer->read();
if (count($answer->nbrAnswers) > 0 && !$form->isSubmitted()) {
$numberAnswers = $answer->nbrAnswers;
}
}
$form->addElement('hidden', 'nb_answers');
//Feedback SELECT
$questionList = $objExercise->selectQuestionList();
$selectQuestion = array();
$selectQuestion[0] = get_lang('SelectTargetQuestion');
if (is_array($questionList)) {
foreach ($questionList as $key => $questionid) {
//To avoid warning messages
if (!is_numeric($questionid)) {
continue;
}
$question = Question::read($questionid);
$selectQuestion[$questionid] = 'Q' . $key . ' :' . cut(
$question->selectTitle(), 20
);
}
}
$selectQuestion[-1] = get_lang('ExitTest');
$list = new LearnpathList(api_get_user_id());
$flatList = $list->get_flat_list();
$selectLpId = array();
$selectLpId[0] = get_lang('SelectTargetLP');
foreach ($flatList as $id => $details) {
$selectLpId[$id] = cut($details['lp_name'], 20);
}
$tempScenario = array();
if ($numberAnswers < 1) {
$numberAnswers = 1;
Display::display_normal_message(
get_lang('YouHaveToCreateAtLeastOneAnswer')
);
}
for ($i = 1; $i <= $numberAnswers; ++$i) {
$form->addHtml('<tr>');
if (isset($answer) && is_object($answer)) {
if ($answer->correct[$i]) {
$correct = $i;
}
$defaults['answer[' . $i . ']'] = $answer->answer[$i];
$defaults['comment[' . $i . ']'] = $answer->comment[$i];
$defaults['weighting[' . $i . ']'] = float_format(
$answer->weighting[$i], 1
);
$itemList = explode('@@', $answer->destination[$i]);
$try = $itemList[0];
$lp = $itemList[1];
$listDestination = $itemList[2];
$url = $itemList[3];
$try = 0;
if ($try != 0) {
$tryResult = 1;
}
$urlResult = '';
if ($url != 0) {
$urlResult = $url;
}
$tempScenario['url' . $i] = $urlResult;
$tempScenario['try' . $i] = $tryResult;
$tempScenario['lp' . $i] = $lp;
$tempScenario['destination' . $i] = $listDestination;
} else {
$defaults['answer[1]'] = get_lang('DefaultUniqueAnswer1');
$defaults['weighting[1]'] = 10;
$defaults['answer[2]'] = get_lang('DefaultUniqueAnswer2');
$defaults['weighting[2]'] = 0;
$tempScenario['destination' . $i] = array('0');
$tempScenario['lp' . $i] = array('0');
}
$defaults['scenario'] = $tempScenario;
$renderer = $form->defaultRenderer();
$renderer->setElementTemplate(
'<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
'correct'
);
$renderer->setElementTemplate(
'<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
'counter[' . $i . ']'
);
$renderer->setElementTemplate(
'<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
'answer[' . $i . ']'
);
$renderer->setElementTemplate(
'<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
'comment[' . $i . ']'
);
$renderer->setElementTemplate(
'<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}</td>',
'weighting[' . $i . ']'
);
$answerNumber = $form->addElement('text', 'counter[' . $i . ']', null, ' value = "' . $i . '"');
$answerNumber->freeze();
$form->addElement('radio', 'correct', null, null, $i, 'class="checkbox"');
$form->addHtmlEditor('answer[' . $i . ']', null, null, true, $editorConfig);
$form->addRule('answer[' . $i . ']', get_lang('ThisFieldIsRequired'), 'required');
if ($objExercise->selectFeedbackType() == EXERCISE_FEEDBACK_TYPE_DIRECT) {
$form->addHtmlEditor('comment[' . $i . ']', null, null, false, $editorConfig);
// Direct feedback
//Adding extra feedback fields
$group = array();
$group['try' . $i] = $form->createElement('checkbox', 'try' . $i, null, get_lang('TryAgain'));
$group['lp' . $i] = $form->createElement(
'select',
'lp' . $i,
get_lang('SeeTheory') . ': ',
$selectLpId
);
$group['destination' . $i] = $form->createElement(
'select',
'destination' . $i,
get_lang('GoToQuestion') . ': ',
$selectQuestion
);
$group['url' . $i] = $form->createElement(
'text', 'url' . $i,
get_lang('Other') . ': ',
array(
'class' => 'col-md-2',
'placeholder' => get_lang('Other')
)
);
$form->addGroup($group, 'scenario');
$renderer->setElementTemplate(
'<td><!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --><br/>{element}',
'scenario'
);
} else {
$form->addHtmlEditor('comment[' . $i . ']', null, null, false, $editorConfig);
}
$form->addText('weighting[' . $i . ']', null, null, array('class' => "col-md-1", 'value' => '0'));
$form->addHtml('</tr>');
}
$form->addHtml('</tbody>');
$form->addHtml('</table>');
global $text, $class;
$buttonGroup = [];
if ($objExercise->edit_exercise_in_lp == true) {
//setting the save button here and not in the question class.php
$buttonGroup[] = $form->addButtonDelete(get_lang('LessAnswer'), 'lessAnswers', true);
$buttonGroup[] = $form->addButtonCreate(get_lang('PlusAnswer'), 'moreAnswers', true);
$buttonGroup[] = $form->addButtonSave($text, 'submitQuestion', true);
$form->addGroup($buttonGroup);
}
// We check the first radio button to be sure a radio button will be check
if ($correct == 0) {
$correct = 1;
}
$defaults['correct'] = $correct;
if (!empty($this->id)) {
$form->setDefaults($defaults);
} else {
if ($this->isContent == 1) {
// Default sample content.
$form->setDefaults($defaults);
} else {
$form->setDefaults(array('correct' => 1));
}
}
$form->setConstants(array('nb_answers' => $numberAnswers));
}
public function processAnswersCreation($form)
{
$questionWeighting = $nbrGoodAnswers = 0;
$correct = $form->getSubmitValue('correct');
$objAnswer = new Answer($this->id);
$numberAnswers = $form->getSubmitValue('nb_answers');
for ($i = 1; $i <= $numberAnswers; $i++) {
$answer = trim($form->getSubmitValue('answer[' . $i . ']'));
$comment = trim($form->getSubmitValue('comment[' . $i . ']'));
$weighting = trim($form->getSubmitValue('weighting[' . $i . ']'));
$scenario = $form->getSubmitValue('scenario');
//$listDestination = $form -> getSubmitValue('destination'.$i);
//$destinationStr = $form -> getSubmitValue('destination'.$i);
$try = $scenario['try' . $i];
$lp = $scenario['lp' . $i];
$destination = $scenario['destination' . $i];
$url = trim($scenario['url' . $i]);
/*
How we are going to parse the destination value
here we parse the destination value which is a string
1@@3@@2;4;4;@@http://www.chamilo.org
where: try_again@@lp_id@@selected_questions@@url
try_again = is 1 || 0
lp_id = id of a learning path (0 if dont select)
selected_questions= ids of questions
url= an url
$destinationStr='';
foreach ($listDestination as $destination_id)
{
$destinationStr.=$destination_id.';';
} */
$goodAnswer = ($correct == $i) ? true : false;
if ($goodAnswer) {
$nbrGoodAnswers++;
$weighting = abs($weighting);
if ($weighting > 0) {
$questionWeighting += $weighting;
}
}
if (empty($try)) {
$try = 0;
}
if (empty($lp)) {
$lp = 0;
}
if (empty($destination)) {
$destination = 0;
}
if ($url == '') {
$url = 0;
}
//1@@1;2;@@2;4;4;@@http://www.chamilo.org
$dest = $try . '@@' . $lp . '@@' . $destination . '@@' . $url;
$objAnswer->createAnswer($answer, $goodAnswer, $comment, $weighting, $i, null, null, $dest);
}
// saves the answers into the data base
$objAnswer->save();
// sets the total weighting of the question
$this->updateWeighting($questionWeighting);
$this->save();
}
public function return_header($feedback_type = null, $counter = null, $score = null)
{
return parent::return_header($feedback_type, $counter, $score);
}
}

@ -2277,6 +2277,7 @@ class Exercise
switch ($answerType) {
// for unique answer
case UNIQUE_ANSWER:
case UNIQUE_ANSWER_IMAGE:
case UNIQUE_ANSWER_NO_OPTION:
if ($from_database) {
$sql = "SELECT answer FROM $TBL_TRACK_ATTEMPT
@ -2937,17 +2938,62 @@ class Exercise
if ($debug) error_log('Showing questions $from '.$from);
//display answers (if not matching type, or if the answer is correct)
if ($answerType != MATCHING || $answerCorrect) {
if (in_array($answerType, array(UNIQUE_ANSWER, UNIQUE_ANSWER_NO_OPTION, MULTIPLE_ANSWER, MULTIPLE_ANSWER_COMBINATION, GLOBAL_MULTIPLE_ANSWER))) {
if (
in_array(
$answerType,
array(
UNIQUE_ANSWER,
UNIQUE_ANSWER_IMAGE,
UNIQUE_ANSWER_NO_OPTION,
MULTIPLE_ANSWER,
MULTIPLE_ANSWER_COMBINATION,
GLOBAL_MULTIPLE_ANSWER
)
)
) {
//if ($origin != 'learnpath') {
ExerciseShowFunctions::display_unique_or_multiple_answer($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect, 0, 0, 0, $results_disabled);
ExerciseShowFunctions::display_unique_or_multiple_answer(
$feedback_type,
$answerType,
$studentChoice,
$answer,
$answerComment,
$answerCorrect,
0,
0,
0,
$results_disabled
);
//}
} elseif ($answerType == MULTIPLE_ANSWER_TRUE_FALSE) {
//if ($origin!='learnpath') {
ExerciseShowFunctions::display_multiple_answer_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect,0,$questionId,0, $results_disabled);
ExerciseShowFunctions::display_multiple_answer_true_false(
$feedback_type,
$answerType,
$studentChoice,
$answer,
$answerComment,
$answerCorrect,
0,
$questionId,
0,
$results_disabled
);
//}
} elseif ($answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE ) {
// if ($origin!='learnpath') {
ExerciseShowFunctions::display_multiple_answer_combination_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect,0,0,0, $results_disabled);
ExerciseShowFunctions::display_multiple_answer_combination_true_false(
$feedback_type,
$answerType,
$studentChoice,
$answer,
$answerComment,
$answerCorrect,
0,
0,
0,
$results_disabled
);
//}
} elseif ($answerType == FILL_IN_BLANKS) {
//if ($origin!='learnpath') {
@ -2959,20 +3005,44 @@ class Exercise
// }
} elseif ($answerType == FREE_ANSWER) {
//if($origin != 'learnpath') {
ExerciseShowFunctions::display_free_answer($feedback_type, $choice, $exeId, $questionId, $questionScore);
ExerciseShowFunctions::display_free_answer(
$feedback_type,
$choice,
$exeId,
$questionId,
$questionScore
);
//}
} elseif ($answerType == ORAL_EXPRESSION) {
// to store the details of open questions in an array to be used in mail
//if ($origin != 'learnpath') {
ExerciseShowFunctions::display_oral_expression_answer($feedback_type, $choice, 0, 0, $nano);
ExerciseShowFunctions::display_oral_expression_answer(
$feedback_type,
$choice,
0,
0,
$nano);
//}
} elseif ($answerType == HOT_SPOT) {
//if ($origin != 'learnpath') {
ExerciseShowFunctions::display_hotspot_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment, $results_disabled);
ExerciseShowFunctions::display_hotspot_answer(
$feedback_type,
$answerId,
$answer,
$studentChoice,
$answerComment,
$results_disabled
);
// }
} elseif ($answerType == HOT_SPOT_ORDER) {
//if ($origin != 'learnpath') {
ExerciseShowFunctions::display_hotspot_order_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment);
ExerciseShowFunctions::display_hotspot_order_answer(
$feedback_type,
$answerId,
$answer,
$studentChoice,
$answerComment
);
//}
} elseif ($answerType == HOT_SPOT_DELINEATION) {
$user_answer = $_SESSION['exerciseResultCoordinates'][$questionId];
@ -3008,8 +3078,11 @@ class Exercise
$missing = $poly_results['s1Only'];
$excess = $poly_results['s2Only'];
//$overlap = round(polygons_overlap($poly_answer,$poly_user)); //this is an area in pixels
if ($debug>0) error_log(__LINE__.' - Polygons results are '.print_r($poly_results,1),0);
//$overlap = round(polygons_overlap($poly_answer,$poly_user));
// //this is an area in pixels
if ($debug > 0) {
error_log(__LINE__ . ' - Polygons results are ' . print_r($poly_results, 1), 0);
}
if ($overlap < 1) {
//shortcut to avoid complicated calculations
@ -3017,15 +3090,20 @@ class Exercise
$final_missing = 100;
$final_excess = 100;
} else {
// the final overlap is the percentage of the initial polygon that is overlapped by the user's polygon
// the final overlap is the percentage of the initial polygon
// that is overlapped by the user's polygon
$final_overlap = round(((float) $overlap / (float) $poly_answer_area) * 100);
if ($debug>1) error_log(__LINE__.' - Final overlap is '.$final_overlap,0);
// the final missing area is the percentage of the initial polygon that is not overlapped by the user's polygon
if ($debug > 1) {
error_log(__LINE__ . ' - Final overlap is ' . $final_overlap, 0);
}
// the final missing area is the percentage of the initial polygon
// that is not overlapped by the user's polygon
$final_missing = 100 - $final_overlap;
if ($debug > 1) {
error_log(__LINE__ . ' - Final missing is ' . $final_missing, 0);
}
// the final excess area is the percentage of the initial polygon's size that is covered by the user's polygon outside of the initial polygon
// the final excess area is the percentage of the initial polygon's size
// that is covered by the user's polygon outside of the initial polygon
$final_excess = round((((float) $poly_user_area - (float) $overlap) / (float) $poly_answer_area) * 100);
if ($debug > 1) {
error_log(__LINE__ . ' - Final excess is ' . $final_excess, 0);
@ -3056,7 +3134,11 @@ class Exercise
}
// if pass
if ($final_overlap>=$threadhold1 && $final_missing<=$threadhold3 && $final_excess<=$threadhold2) {
if (
$final_overlap >= $threadhold1 &&
$final_missing <= $threadhold3 &&
$final_excess <= $threadhold2
) {
$next=1; //go to the oars
$result_comment=get_lang('Acceptable');
$final_answer = 1; // do not update with update_exercise_attempt
@ -3123,7 +3205,9 @@ class Exercise
} elseif($answerType == MATCHING) {
echo '<tr>';
echo '<td>' . $answerMatching[$answerId] . '</td>';
echo '<td>'.$user_answer.' / <b><span style="color: #008000;">'.$answerMatching[$answerCorrect].'</span></b></td>';
echo '<td>' . $user_answer . ' / <b>'
. '<span style="color: #008000;">' . $answerMatching[$answerCorrect] . '</span>'
. '</b></td>';
echo '</tr>';
}
}
@ -3132,56 +3216,166 @@ class Exercise
switch ($answerType) {
case UNIQUE_ANSWER :
case UNIQUE_ANSWER_IMAGE:
case UNIQUE_ANSWER_NO_OPTION:
case MULTIPLE_ANSWER :
case GLOBAL_MULTIPLE_ANSWER :
case MULTIPLE_ANSWER_COMBINATION :
if ($answerId == 1) {
ExerciseShowFunctions::display_unique_or_multiple_answer($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect,$exeId,$questionId,$answerId, $results_disabled);
ExerciseShowFunctions::display_unique_or_multiple_answer(
$feedback_type,
$answerType,
$studentChoice,
$answer,
$answerComment,
$answerCorrect,
$exeId,
$questionId,
$answerId,
$results_disabled
);
} else {
ExerciseShowFunctions::display_unique_or_multiple_answer($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect,$exeId,$questionId,"", $results_disabled);
ExerciseShowFunctions::display_unique_or_multiple_answer(
$feedback_type,
$answerType,
$studentChoice,
$answer,
$answerComment,
$answerCorrect,
$exeId,
$questionId,
"",
$results_disabled
);
}
break;
case MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE:
if ($answerId == 1) {
ExerciseShowFunctions::display_multiple_answer_combination_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect,$exeId,$questionId,$answerId, $results_disabled);
ExerciseShowFunctions::display_multiple_answer_combination_true_false(
$feedback_type,
$answerType,
$studentChoice,
$answer,
$answerComment,
$answerCorrect,
$exeId,
$questionId,
$answerId,
$results_disabled
);
} else {
ExerciseShowFunctions::display_multiple_answer_combination_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect,$exeId,$questionId,"", $results_disabled);
ExerciseShowFunctions::display_multiple_answer_combination_true_false(
$feedback_type,
$answerType,
$studentChoice,
$answer,
$answerComment,
$answerCorrect,
$exeId,
$questionId,
"",
$results_disabled
);
}
break;
case MULTIPLE_ANSWER_TRUE_FALSE :
if ($answerId == 1) {
ExerciseShowFunctions::display_multiple_answer_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect,$exeId,$questionId,$answerId, $results_disabled);
ExerciseShowFunctions::display_multiple_answer_true_false(
$feedback_type,
$answerType,
$studentChoice,
$answer,
$answerComment,
$answerCorrect,
$exeId,
$questionId,
$answerId,
$results_disabled
);
} else {
ExerciseShowFunctions::display_multiple_answer_true_false($feedback_type, $answerType, $studentChoice, $answer, $answerComment, $answerCorrect,$exeId,$questionId, "", $results_disabled);
ExerciseShowFunctions::display_multiple_answer_true_false(
$feedback_type,
$answerType,
$studentChoice,
$answer,
$answerComment,
$answerCorrect,
$exeId,
$questionId,
"",
$results_disabled
);
}
break;
case FILL_IN_BLANKS:
ExerciseShowFunctions::display_fill_in_blanks_answer($feedback_type, $answer,$exeId,$questionId);
ExerciseShowFunctions::display_fill_in_blanks_answer(
$feedback_type,
$answer,
$exeId,
$questionId
);
break;
case CALCULATED_ANSWER:
ExerciseShowFunctions::display_calculated_answer($feedback_type, $answer, $exeId, $questionId);
ExerciseShowFunctions::display_calculated_answer(
$feedback_type,
$answer,
$exeId,
$questionId
);
break;
case FREE_ANSWER:
echo ExerciseShowFunctions::display_free_answer($feedback_type, $choice, $exeId, $questionId, $questionScore);
echo ExerciseShowFunctions::display_free_answer(
$feedback_type,
$choice,
$exeId,
$questionId,
$questionScore
);
break;
case ORAL_EXPRESSION:
echo '<tr>
<td valign="top">'.ExerciseShowFunctions::display_oral_expression_answer($feedback_type, $choice, $exeId, $questionId, $nano).'</td>
<td valign="top">' . ExerciseShowFunctions::display_oral_expression_answer(
$feedback_type,
$choice,
$exeId,
$questionId,
$nano
) . '</td>
</tr>
</table>';
break;
case HOT_SPOT:
ExerciseShowFunctions::display_hotspot_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment, $results_disabled);
ExerciseShowFunctions::display_hotspot_answer(
$feedback_type,
$answerId,
$answer,
$studentChoice,
$answerComment,
$results_disabled);
break;
case HOT_SPOT_DELINEATION:
$user_answer = $user_array;
if ($next) {
//$tbl_track_e_hotspot = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
// Save into db
/* $sql = "INSERT INTO $tbl_track_e_hotspot (hotspot_user_id, hotspot_course_code, hotspot_exe_id, hotspot_question_id, hotspot_answer_id, hotspot_correct, hotspot_coordinate )
VALUES ('".Database::escape_string($_user['user_id'])."', '".Database::escape_string($_course['id'])."', '".Database::escape_string($exeId)."', '".Database::escape_string($questionId)."', '".Database::escape_string($answerId)."', '".Database::escape_string($studentChoice)."', '".Database::escape_string($user_array)."')";
$result = Database::query($sql,__FILE__,__LINE__);*/
/* $sql = "INSERT INTO $tbl_track_e_hotspot (
* hotspot_user_id,
* hotspot_course_code,
* hotspot_exe_id,
* hotspot_question_id,
* hotspot_answer_id,
* hotspot_correct,
* hotspot_coordinate
* )
VALUES (
* '".Database::escape_string($_user['user_id'])."',
* '".Database::escape_string($_course['id'])."',
* '".Database::escape_string($exeId)."', '".Database::escape_string($questionId)."',
* '".Database::escape_string($answerId)."',
* '".Database::escape_string($studentChoice)."',
* '".Database::escape_string($user_array)."')";
$result = Database::query($sql,__FILE__,__LINE__);
*/
$user_answer = $user_array;
// we compare only the delineation not the other points
@ -3237,7 +3431,6 @@ class Exercise
$threadhold1 = $threadhold_items[0]; // overlap
$threadhold2 = $threadhold_items[1]; // excess
$threadhold3 = $threadhold_items[2]; //missing
// if is delineation
if ($answerId === 1) {
//setting colors
@ -3320,12 +3513,20 @@ class Exercise
}
break;
case HOT_SPOT_ORDER:
ExerciseShowFunctions::display_hotspot_order_answer($feedback_type, $answerId, $answer, $studentChoice, $answerComment);
ExerciseShowFunctions::display_hotspot_order_answer(
$feedback_type,
$answerId,
$answer,
$studentChoice,
$answerComment
);
break;
case MATCHING:
echo '<tr>';
echo '<td>' . $answerMatching[$answerId] . '</td>';
echo '<td>'.$user_answer.' / <b><span style="color: #008000;">'.$answerMatching[$answerCorrect].'</span></b></td>';
echo '<td>' . $user_answer . ' / <b>'
. '<span style="color: #008000;">' . $answerMatching[$answerCorrect] . '</span></b>'
. '</td>';
echo '</tr>';
break;
@ -3364,7 +3565,8 @@ class Exercise
$counter = 1;
$correct_answer = true;
foreach ($real_answers as $my_answer) {
if ($debug) error_log(" my_answer: $my_answer answer_correct_array[counter]: ".$answer_correct_array[$counter]);
if ($debug)
error_log(" my_answer: $my_answer answer_correct_array[counter]: ".$answer_correct_array[$counter]);
if ($my_answer != $answer_correct_array[$counter]) {
$correct_answer = false;
break;
@ -3398,8 +3600,10 @@ class Exercise
'threadhold3'=> $threadhold3,
);
if ($from == 'exercise_result') {
// if answer is hotspot. To the difference of exercise_show.php, we use the results from the session (from_db=0)
// TODO Change this, because it is wrong to show the user some results that haven't been stored in the database yet
// if answer is hotspot. To the difference of exercise_show.php,
// we use the results from the session (from_db=0)
// TODO Change this, because it is wrong to show the user
// some results that haven't been stored in the database yet
if ($answerType == HOT_SPOT || $answerType == HOT_SPOT_ORDER || $answerType == HOT_SPOT_DELINEATION ) {
if ($debug) error_log('$from AND this is a hotspot kind of question ');
@ -3446,17 +3650,20 @@ class Exercise
<tr class="row_even">
<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>
<td><div style="color:' . $overlap_color . '">'
. (($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>
<td><div style="color:' . $excess_color . '">'
. (($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>
<td><div style="color:' . $missing_color . '">'
. (($final_missing < 0) ? 0 : intval($final_missing)) . '</div></td>
</tr>
</table>';
if ($next == 0) {
@ -3490,13 +3697,21 @@ class Exercise
//save the score attempts
if (1) {
$final_answer = $hotspot_delineation_result[1]; //getting the answer 1 or 0 comes from exercise_submit_modal.php
//getting the answer 1 or 0 comes from exercise_submit_modal.php
$final_answer = $hotspot_delineation_result[1];
if ($final_answer == 0) {
$questionScore = 0;
}
Event::saveQuestionAttempt($questionScore, 1, $quesId, $exeId, 0); // we always insert the answer_id 1 = delineation
// we always insert the answer_id 1 = delineation
Event::saveQuestionAttempt($questionScore, 1, $quesId, $exeId, 0);
//in delineation mode, get the answer from $hotspot_delineation_result[1]
Event::saveExerciseAttemptHotspot($exeId,$quesId,1, $hotspot_delineation_result[1], $exerciseResultCoordinates[$quesId]);
Event::saveExerciseAttemptHotspot(
$exeId,
$quesId,
1,
$hotspot_delineation_result[1],
$exerciseResultCoordinates[$quesId]
);
} else {
if ($final_answer==0) {
$questionScore = 0;
@ -3530,8 +3745,18 @@ class Exercise
<td colspan="2">';
echo '<i>'.get_lang('HotSpot').'</i><br /><br />';
echo '<object type="application/x-shockwave-flash" data="'.api_get_path(WEB_CODE_PATH).'plugin/hotspot/hotspot_solution.swf?modifyAnswers='.Security::remove_XSS($questionId).'&exe_id='.$exeId.'&from_db=1" width="552" height="352">
<param name="movie" value="../plugin/hotspot/hotspot_solution.swf?modifyAnswers='.Security::remove_XSS($questionId).'&exe_id='.$exeId.'&from_db=1" />
echo '<object type="application/x-shockwave-flash" data="'
. api_get_path(WEB_CODE_PATH)
. 'plugin/hotspot/hotspot_solution.swf?modifyAnswers='
. Security::remove_XSS($questionId)
. '&exe_id='
. $exeId
. '&from_db=1" width="552" height="352">
<param name="movie" value="../plugin/hotspot/hotspot_solution.swf?modifyAnswers='
. Security::remove_XSS($questionId)
. '&exe_id='
. $exeId
. '&from_db=1" />
</object>';
echo '</td>
</tr>';
@ -3564,8 +3789,17 @@ class Exercise
$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);
if ($debug) error_log('result =>'.$questionScore.' '.$ans.':'.$choice[$ans]);
Event::saveQuestionAttempt(
$questionScore,
$ans . ':' . $choice[$ans],
$quesId,
$exeId,
$i,
$this->id
);
if ($debug) {
error_log('result =>' . $questionScore . ' ' . $ans . ':' . $choice[$ans]);
}
}
} else {
Event::saveQuestionAttempt($questionScore, 0, $quesId, $exeId, 0, $this->id);
@ -3574,7 +3808,9 @@ class Exercise
if ($choice != 0) {
$reply = array_keys($choice);
if ($debug) error_log("reply ".print_r($reply, 1)."");
if ($debug) {
error_log("reply " . print_r($reply, 1) . "");
}
for ($i = 0; $i < sizeof($reply); $i++) {
$ans = $reply[$i];
Event::saveQuestionAttempt($questionScore, $ans, $quesId, $exeId, $i, $this->id);
@ -3604,8 +3840,7 @@ class Exercise
} elseif ($answerType == ORAL_EXPRESSION) {
$answer = $choice;
Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id, $nano);
} elseif ($answerType == UNIQUE_ANSWER || $answerType == UNIQUE_ANSWER_NO_OPTION) {
} elseif (in_array($answerType, [UNIQUE_ANSWER, UNIQUE_ANSWER_IMAGE, UNIQUE_ANSWER_NO_OPTION])) {
$answer = $choice;
Event::saveQuestionAttempt($questionScore, $answer, $quesId, $exeId, 0, $this->id);
// } elseif ($answerType == HOT_SPOT || $answerType == HOT_SPOT_DELINEATION) {
@ -3664,7 +3899,14 @@ class Exercise
return false;
}
$url_email = api_get_path(WEB_CODE_PATH).'exercice/exercise_show.php?'.api_get_cidreq().'&id_session='.$sessionId.'&id='.$exe_id.'&action=qualify';
$url_email = api_get_path(WEB_CODE_PATH)
. 'exercice/exercise_show.php?'
. api_get_cidreq()
. '&id_session='
. $sessionId
. '&id='
. $exe_id
. '&action=qualify';
$user_info = UserManager::get_user_info_by_id(api_get_user_id());
$msg = '<p>'.get_lang('ExerciseAttempted').' :</p>
@ -3733,7 +3975,14 @@ class Exercise
$courseCode = api_get_course_id();
$course_info = api_get_course_info($courseCode);
$url_email = api_get_path(WEB_CODE_PATH).'exercice/exercise_show.php?'.api_get_cidreq().'&id_session='.api_get_session_id().'&id='.$exe_id.'&action=qualify';
$url_email = api_get_path(WEB_CODE_PATH)
. 'exercice/exercise_show.php?'
. api_get_cidreq()
. '&id_session='
. api_get_session_id()
. '&id='
. $exe_id
. '&action=qualify';
$user_info = UserManager::get_user_info_by_id(api_get_user_id());
$msg = '<p>'.get_lang('OpenQuestionsAttempted').' :</p>
@ -3823,7 +4072,14 @@ class Exercise
$courseCode = api_get_course_id();
$course_info = api_get_course_info($courseCode);
$url_email = api_get_path(WEB_CODE_PATH).'exercice/exercise_show.php?'.api_get_cidreq().'&id_session='.api_get_session_id().'&id='.$exe_id.'&action=qualify';
$url_email = api_get_path(WEB_CODE_PATH)
. 'exercice/exercise_show.php?'
. api_get_cidreq()
. '&id_session='
. api_get_session_id()
. '&id='
. $exe_id
. '&action=qualify';
$user_info = UserManager::get_user_info_by_id(api_get_user_id());
$oral_question_list = null;
@ -3833,7 +4089,8 @@ class Exercise
$answer_type = $item['answer_type'];
if (!empty($question) && !empty($answer) && $answer_type == ORAL_EXPRESSION) {
$oral_question_list.='<br /><table width="730" height="136" border="0" cellpadding="3" cellspacing="3"><tr>
$oral_question_list.='<br /><table width="730" height="136" border="0" cellpadding="3" cellspacing="3">
<tr>
<td width="220" valign="top" bgcolor="#E5EDF8">&nbsp;&nbsp;'.get_lang('Question').'</td>
<td width="473" valign="top" bgcolor="#F3F3F3">'.$question.'</td>
</tr>
@ -3983,8 +4240,36 @@ class Exercise
$sessionId = api_get_session_id();
$course_id = api_get_course_int_id();
// Save a new quiz
$sql = "INSERT INTO $tbl_quiz (c_id, title, type, random, active, results_disabled, max_attempt, start_time,end_time,feedback_type,expired_time, session_id, propagate_neg)
VALUES('$course_id', '".$title."', $type, $random, $active, $results_disabled, $max_attempt,'','', $feedback, $expired_time, $sessionId, $propagateNegative)";
$sql = "INSERT INTO $tbl_quiz (
c_id,
title,
type,
random,
active,
results_disabled,
max_attempt,
start_time,
end_time,
feedback_type,
expired_time,
session_id,
propagate_neg
)
VALUES (
'$course_id',
'$title',
$type,
$random,
$active,
$results_disabled,
$max_attempt,
'',
'',
$feedback,
$expired_time,
$sessionId,
$propagateNegative
)";
Database::query($sql);
$quiz_id = Database::insert_id();
@ -4101,7 +4386,10 @@ class Exercise
}
//3. We check if the time limits are on
$limit_time_exists = ((!empty($this->start_time) && $this->start_time != '0000-00-00 00:00:00') || (!empty($this->end_time) && $this->end_time != '0000-00-00 00:00:00')) ? true : false;
$limit_time_exists = (
(!empty($this->start_time) && $this->start_time != '0000-00-00 00:00:00') ||
(!empty($this->end_time) && $this->end_time != '0000-00-00 00:00:00')
) ? true : false;
if ($limit_time_exists) {
$time_now = time();
@ -4111,18 +4399,28 @@ class Exercise
}
if ($is_visible == false) {
$message = sprintf(get_lang('ExerciseAvailableFromX'), api_convert_and_format_date($this->start_time));
$message = sprintf(
get_lang('ExerciseAvailableFromX'),
api_convert_and_format_date($this->start_time)
);
}
if ($is_visible == true) {
if ($this->end_time != '0000-00-00 00:00:00') {
$is_visible = ((api_strtotime($this->end_time, 'UTC') > $time_now) > 0) ? true : false;
if ($is_visible == false) {
$message = sprintf(get_lang('ExerciseAvailableUntilX'), api_convert_and_format_date($this->end_time));
$message = sprintf(
get_lang('ExerciseAvailableUntilX'),
api_convert_and_format_date($this->end_time)
);
}
}
}
if ($is_visible == false && $this->start_time != '0000-00-00 00:00:00' && $this->end_time != '0000-00-00 00:00:00') {
if (
$is_visible == false &&
$this->start_time != '0000-00-00 00:00:00' &&
$this->end_time != '0000-00-00 00:00:00'
) {
$message = sprintf(
get_lang('ExerciseWillBeActivatedFromXToY'),
api_convert_and_format_date($this->start_time),
@ -4170,7 +4468,7 @@ class Exercise
{
$TBL_LP_ITEM = Database::get_course_table(TABLE_LP_ITEM);
$sql = "SELECT max_score FROM $TBL_LP_ITEM
WHERE c_id = ".$this->course_id." AND item_type = '".TOOL_QUIZ."' AND path = '".$this->id."'";
WHERE c_id = {$this->course_id} AND item_type = '" . TOOL_QUIZ . "' AND path = '{$this->id}'";
$result = Database::query($sql);
if (Database::num_rows($result) > 0) {
return true;
@ -4254,7 +4552,13 @@ class Exercise
if ($this->random == -1) {
$number_of_random_question = count($this->questionList);
}
$questionList = array_merge($questionList, TestCategory::getNElementsFromArray($tabquestion, $number_of_random_question));
$questionList = array_merge(
$questionList,
TestCategory::getNElementsFromArray(
$tabquestion,
$number_of_random_question
)
);
}
// shuffle the question list if test is not grouped by categories
if ($isRandomByCategory == 1) {
@ -4262,7 +4566,8 @@ class Exercise
}
$tabres = $questionList;
} else {
// Problem, random by category has been selected and we have no $this->isRandom nnumber of question selected
// Problem, random by category has been selected and
// we have no $this->isRandom number of question selected
// Should not happened
}
}
@ -4428,7 +4733,17 @@ class Exercise
function return_time_left_div()
{
$html = '<div id="clock_warning" style="display:none">'.Display::return_message(get_lang('ReachedTimeLimit'), 'warning').' '.sprintf(get_lang('YouWillBeRedirectedInXSeconds'), '<span id="counter_to_redirect" class="red_alert"></span>').'</div>';
$html = '<div id="clock_warning" style="display:none">';
$html .= Display::return_message(
get_lang('ReachedTimeLimit'),
'warning'
);
$html .= ' ';
$html .= sprintf(
get_lang('YouWillBeRedirectedInXSeconds'),
'<span id="counter_to_redirect" class="red_alert"></span>'
);
$html .= '</div>';
$html .= '<div id="exercise_clock_warning" class="well count_down"></div>';
return $html;
}
@ -4463,7 +4778,8 @@ class Exercise
/**
* Calculate the max_score of the quiz, depending of question inside, and quiz advanced option
*/
public function get_max_score() {
public function get_max_score()
{
$out_max_score = 0;
$tab_question_list = $this->selectQuestionList(true); // list of question's id !!! the array key start at 1 !!!
// test is randomQuestions - see field random of test

@ -1128,6 +1128,7 @@ if (!empty($error)) {
echo Display::div($exercise_actions, array('class'=>'exercise_actions'));
}
echo '</form>';
echo '</div>';
}
if ($origin != 'learnpath') {

@ -43,9 +43,13 @@ abstract class Question
MULTIPLE_ANSWER_COMBINATION => array('multiple_answer_combination.class.php', 'MultipleAnswerCombination'),
UNIQUE_ANSWER_NO_OPTION => array('unique_answer_no_option.class.php', 'UniqueAnswerNoOption'),
MULTIPLE_ANSWER_TRUE_FALSE => array('multiple_answer_true_false.class.php', 'MultipleAnswerTrueFalse'),
MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE => array('multiple_answer_combination_true_false.class.php', 'MultipleAnswerCombinationTrueFalse'),
MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE => array(
'multiple_answer_combination_true_false.class.php',
'MultipleAnswerCombinationTrueFalse'
),
GLOBAL_MULTIPLE_ANSWER => array('global_multiple_answer.class.php' , 'GlobalMultipleAnswer'),
CALCULATED_ANSWER => array('calculated_answer.class.php' , 'CalculatedAnswer')
CALCULATED_ANSWER => array('calculated_answer.class.php' , 'CalculatedAnswer'),
UNIQUE_ANSWER_IMAGE => ['UniqueAnswerImage.php', 'UniqueAnswerImage']
//MEDIA_QUESTION => array('media_question.class.php' , 'MediaQuestion')
);
@ -365,13 +369,18 @@ abstract class Question
foreach ($category_list as $category_id) {
$category_id = intval($category_id);
$question_id = intval($this->id);
$sql = "SELECT count(*) AS nb FROM $TBL_QUESTION_REL_CATEGORY
WHERE category_id = $category_id AND question_id = $question_id AND c_id=".api_get_course_int_id();
$sql = "SELECT count(*) AS nb
FROM $TBL_QUESTION_REL_CATEGORY
WHERE
category_id = $category_id
AND question_id = $question_id
AND c_id=".api_get_course_int_id();
$res = Database::query($sql);
$row = Database::fetch_array($res);
if ($row['nb'] > 0) {
//DO nothing
//$sql = "UPDATE $TBL_QUESTION_REL_CATEGORY SET category_id = $category_id WHERE question_id=$question_id AND c_id=".api_get_course_int_id();
//$sql = "UPDATE $TBL_QUESTION_REL_CATEGORY SET category_id = $category_id
//WHERE question_id=$question_id AND c_id=".api_get_course_int_id();
//$res = Database::query($sql);
} else {
$sql = "INSERT INTO $TBL_QUESTION_REL_CATEGORY (c_id, question_id, category_id)
@ -403,10 +412,12 @@ abstract class Question
$res = Database::query($sql);
$row = Database::fetch_array($res);
if ($row['nb'] > 0){
$sql = "UPDATE $TBL_QUESTION_REL_CATEGORY SET category_id=$category_id WHERE question_id=$question_id AND c_id=".api_get_course_int_id();
$sql = "UPDATE $TBL_QUESTION_REL_CATEGORY SET category_id = $category_id
WHERE question_id = $question_id AND c_id = " . api_get_course_int_id();
Database::query($sql);
} else {
$sql = "INSERT INTO $TBL_QUESTION_REL_CATEGORY VALUES (".api_get_course_int_id().", $question_id, $category_id)";
$sql = "INSERT INTO $TBL_QUESTION_REL_CATEGORY
VALUES (" . api_get_course_int_id() . ", $question_id, $category_id)";
Database::query($sql);
}
}
@ -467,10 +478,13 @@ abstract class Question
// if we really change the type
if ($type != $this->type) {
// if we don't change from "unique answer" to "multiple answers" (or conversely)
if (!in_array($this->type, array(UNIQUE_ANSWER,MULTIPLE_ANSWER)) || !in_array($type,array(UNIQUE_ANSWER,MULTIPLE_ANSWER))) {
if (
!in_array($this->type, array(UNIQUE_ANSWER, MULTIPLE_ANSWER)) ||
!in_array($type, array(UNIQUE_ANSWER, MULTIPLE_ANSWER))
) {
// removes old answers
$sql = "DELETE FROM $TBL_REPONSES
WHERE c_id = $course_id AND question_id = ".intval($this->id)."";
WHERE c_id = $course_id AND question_id = " . intval($this->id);
Database::query($sql);
}
@ -511,13 +525,19 @@ abstract class Question
$o_img->send_image($picturePath . '/' . $this->picture, -1, 'jpg');
$document_id = add_document(
$this->course,
'/images/' . $this->picture, 'file',
'/images/' . $this->picture,
'file',
filesize($picturePath . '/' . $this->picture),
$this->picture
);
if ($document_id) {
return api_item_property_update($this->course, TOOL_DOCUMENT,
$document_id, 'DocumentAdded', api_get_user_id());
return api_item_property_update(
$this->course,
TOOL_DOCUMENT,
$document_id,
'DocumentAdded',
api_get_user_id()
);
}
}
@ -525,8 +545,8 @@ abstract class Question
}
/**
* Resizes a picture || Warning!: can only be called after uploadPicture, or if picture is already available in object.
*
* Resizes a picture || Warning!: can only be called after uploadPicture,
* or if picture is already available in object.
* @author Toon Keppens
* @param string $Dimension - Resizing happens proportional according to given dimension: height|width|any
* @param integer $Max - Maximum size
@ -638,9 +658,21 @@ abstract class Question
WHERE c_id = $course_id AND id='" . intval($questionId) . "'";
Database::query($sql);
$document_id = add_document($course_info, '/images/'.$picture, 'file', filesize($destination_path.'/'.$picture), $picture);
$document_id = add_document(
$course_info,
'/images/' . $picture,
'file',
filesize($destination_path . '/' . $picture),
$picture
);
if ($document_id) {
return api_item_property_update($course_info, TOOL_DOCUMENT, $document_id, 'DocumentAdded', api_get_user_id());
return api_item_property_update(
$course_info,
TOOL_DOCUMENT,
$document_id,
'DocumentAdded',
api_get_user_id()
);
}
}
@ -736,7 +768,8 @@ abstract class Question
// question already exists
if(!empty($id)) {
$sql="UPDATE $TBL_QUESTIONS SET
$sql = "UPDATE $TBL_QUESTIONS
SET
question = '" . Database::escape_string($question) . "',
description = '" . Database::escape_string($description) . "',
ponderation = '" . Database::escape_string($weighting) . "',
@ -745,7 +778,7 @@ abstract class Question
picture = '" . Database::escape_string($picture) . "',
extra = '" . Database::escape_string($extra) . "',
level = '" . Database::escape_string($level) . "'
WHERE c_id = $c_id AND id = ".intval($id)."";
WHERE c_id = $c_id AND id = " . intval($id);
Database::query($sql);
$this->saveCategory($category);
@ -782,7 +815,10 @@ abstract class Question
$current_position = Database::result($result,0,0);
$this->updatePosition($current_position+1);
$position = $this->position;
$sql = "INSERT INTO $TBL_QUESTIONS (c_id, question, description, ponderation, position, type, picture, extra, level) VALUES (
$sql = "INSERT INTO $TBL_QUESTIONS (
c_id, question, description, ponderation, position, type, picture, extra, level
)
VALUES (
$c_id,
'" . Database::escape_string($question) . "',
'" . Database::escape_string($description) . "',
@ -814,8 +850,21 @@ abstract class Question
$TBL_ANSWERS = Database::get_course_table(
TABLE_QUIZ_ANSWER
);
$sql = "INSERT INTO $TBL_ANSWERS (c_id, question_id , answer, correct, comment, ponderation, position, hotspot_coordinates, hotspot_type)
VALUES (".$c_id.", ".intval($this->id).", '', NULL , '', '10' , '1', '0;0|0|0', 'square')";
$sql = "INSERT INTO $TBL_ANSWERS (
c_id, question_id , answer, correct, comment, ponderation, position, hotspot_coordinates,
hotspot_type
)
VALUES (
$c_id,
" . intval($this->id) . ",
'',
NULL,
'',
'10',
'1',
'0;0|0|0',
'square'
)";
Database::query($sql);
$id = Database::insert_id();
if ($id) {
@ -828,8 +877,13 @@ abstract class Question
$TBL_ANSWERS = Database::get_course_table(
TABLE_QUIZ_ANSWER
);
$sql = "INSERT INTO $TBL_ANSWERS (c_id, question_id , answer , correct , comment , ponderation , position , hotspot_coordinates , hotspot_type )
VALUES (".$c_id.", ".intval($this->id).", '', NULL , '', '10' , '1', '0;0|0|0', 'delineation')";
$sql = "INSERT INTO $TBL_ANSWERS (
c_id, question_id, answer, correct, comment, ponderation, position, hotspot_coordinates,
hotspot_type
)
VALUES (
$c_id, " . intval($this->id) . ", '', NULL , '', '10' , '1', '0;0|0|0', 'delineation'
)";
Database::query($sql);
$id = Database::insert_id();
@ -875,10 +929,13 @@ abstract class Question
$tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
if ($addQs || $rmQs) {
//there's only one row per question on normal db and one document per question on search engine db
$sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_second_level=%s LIMIT 1';
$sql = 'SELECT * FROM %
WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_second_level=%s LIMIT 1';
$sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_QUIZ, $this->id);
} else {
$sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s AND ref_id_second_level=%s LIMIT 1';
$sql = 'SELECT * FROM %s
WHERE course_code=\'%s\' AND tool_id=\'%s\'
AND ref_id_high_level=%s AND ref_id_second_level=%s LIMIT 1';
$sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_QUIZ, $exerciseId, $this->id);
}
$res = Database::query($sql);
@ -902,8 +959,14 @@ abstract class Question
if ($se_doc !== FALSE) {
if (($se_doc_data = $di->get_document_data($se_doc)) !== FALSE) {
$se_doc_data = unserialize($se_doc_data);
if (isset($se_doc_data[SE_DATA]['type']) && $se_doc_data[SE_DATA]['type'] == SE_DOCTYPE_EXERCISE_QUESTION) {
if (isset($se_doc_data[SE_DATA]['exercise_ids']) && is_array($se_doc_data[SE_DATA]['exercise_ids'])) {
if (
isset($se_doc_data[SE_DATA]['type']) &&
$se_doc_data[SE_DATA]['type'] == SE_DOCTYPE_EXERCISE_QUESTION
) {
if (
isset($se_doc_data[SE_DATA]['exercise_ids']) &&
is_array($se_doc_data[SE_DATA]['exercise_ids'])
) {
foreach ($se_doc_data[SE_DATA]['exercise_ids'] as $old_value) {
if (!in_array($old_value, $question_exercises)) {
$question_exercises[] = $old_value;
@ -927,7 +990,11 @@ abstract class Question
$xapian_data = array(
SE_COURSE_ID => $course_id,
SE_TOOL_ID => TOOL_QUIZ,
SE_DATA => array('type' => SE_DOCTYPE_EXERCISE_QUESTION, 'exercise_ids' => $question_exercises, 'question_id' => (int)$this->id),
SE_DATA => array(
'type' => SE_DOCTYPE_EXERCISE_QUESTION,
'exercise_ids' => $question_exercises,
'question_id' => (int)$this->id
),
SE_USER => (int)api_get_user_id(),
);
$ic_slide->xapian_data = serialize($xapian_data);
@ -946,23 +1013,46 @@ abstract class Question
if ($did || $rmQs) {
// save it to db
if ($addQs || $rmQs) {
$sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_second_level=\'%s\'';
$sql = "DELETE FROM %s
WHERE course_code = '%s' AND tool_id = '%s' AND ref_id_second_level = '%s'";
$sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_QUIZ, $this->id);
} else {
$sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=\'%s\' AND ref_id_second_level=\'%s\'';
$sql = "DELETE FROM %S
WHERE
course_code = '%s'
AND tool_id = '%s'
AND tool_id = '%s'
AND ref_id_high_level = '%s'
AND ref_id_second_level = '%s'";
$sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_QUIZ, $exerciseId, $this->id);
}
Database::query($sql);
if ($rmQs) {
if (!empty($question_exercises)) {
$sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, ref_id_second_level, search_did)
VALUES (NULL , \'%s\', \'%s\', %s, %s, %s)';
$sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_QUIZ, array_shift($question_exercises), $this->id, $did);
$sql = "INSERT INTO %s (
id, course_code, tool_id, ref_id_high_level, ref_id_second_level, search_did
)
VALUES (
NULL, '%s', '%s', %s, %s, %s
)";
$sql = sprintf(
$sql,
$tbl_se_ref,
$course_id,
TOOL_QUIZ,
array_shift($question_exercises),
$this->id,
$did
);
Database::query($sql);
}
} else {
$sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, ref_id_second_level, search_did)
VALUES (NULL , \'%s\', \'%s\', %s, %s, %s)';
$sql = "INSERT INTO %s (
id, course_code, tool_id, ref_id_high_level, ref_id_second_level, search_did
)
VALUES (
NULL , '%s', '%s', %s, %s, %s
)";
$sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_QUIZ, $exerciseId, $this->id, $did);
Database::query($sql);
}
@ -990,8 +1080,8 @@ abstract class Question
$new_exercise->read($exerciseId);
$count = $new_exercise->selectNbrQuestions();
$count++;
$sql="INSERT INTO $exerciseRelQuestionTable (c_id, question_id, exercice_id, question_order) VALUES
({$this->course['real_id']}, ".intval($id).", ".intval($exerciseId).", '$count' )";
$sql="INSERT INTO $exerciseRelQuestionTable (c_id, question_id, exercice_id, question_order)
VALUES ({$this->course['real_id']}, " . intval($id) . ", " . intval($exerciseId) . ", '$count')";
Database::query($sql);
// we do not want to reindex if we had just saved adnd indexed the question
@ -1026,20 +1116,31 @@ abstract class Question
// deletes the position in the array containing the wanted exercise ID
unset($this->exerciseList[$pos]);
//update order of other elements
$sql = "SELECT question_order FROM $TBL_EXERCICE_QUESTION
WHERE c_id = $course_id AND question_id = ".intval($id)." AND exercice_id = ".intval($exerciseId)."";
$sql = "SELECT question_order
FROM $TBL_EXERCICE_QUESTION
WHERE
c_id = $course_id
AND question_id = " . intval($id) . "
AND exercice_id = " . intval($exerciseId);
$res = Database::query($sql);
if (Database::num_rows($res)>0) {
$row = Database::fetch_array($res);
if (!empty($row['question_order'])) {
$sql = "UPDATE $TBL_EXERCICE_QUESTION SET question_order = question_order-1
WHERE c_id = $course_id AND exercice_id = ".intval($exerciseId)." AND question_order > ".$row['question_order'];
$sql = "UPDATE $TBL_EXERCICE_QUESTION
SET question_order = question_order-1
WHERE
c_id = $course_id
AND exercice_id = " . intval($exerciseId) . "
AND question_order > " . $row['question_order'];
$res = Database::query($sql);
}
}
$sql = "DELETE FROM $TBL_EXERCICE_QUESTION
WHERE c_id = $course_id AND question_id = ".intval($id)." AND exercice_id = ".intval($exerciseId)."";
WHERE
c_id = $course_id
AND question_id = " . intval($id) . "
AND exercice_id = " . intval($exerciseId);
Database::query($sql);
return true;
@ -1077,7 +1178,10 @@ abstract class Question
if (!empty($row['question_order'])) {
$sql = "UPDATE $TBL_EXERCICE_QUESTION
SET question_order = question_order-1
WHERE c_id = $course_id AND exercice_id = ".intval($row['exercice_id'])." AND question_order > ".$row['question_order'];
WHERE
c_id= $course_id
AND exercice_id = " . intval($row['exercice_id']) . "
AND question_order > " . $row['question_order'];
Database::query($sql);
}
}
@ -1159,8 +1263,19 @@ abstract class Question
$options = self::readQuestionOption($this->id, $this->course['real_id']);
//Inserting in the new course db / or the same course db
$sql = "INSERT INTO $TBL_QUESTIONS (c_id, question, description, ponderation, position, type, level, extra )
VALUES('$course_id', '".Database::escape_string($question)."','".Database::escape_string($description)."','".Database::escape_string($weighting)."','".Database::escape_string($position)."','".Database::escape_string($type)."' ,'".Database::escape_string($level)."' ,'".Database::escape_string($extra)."' )";
$sql = "INSERT INTO $TBL_QUESTIONS (
c_id, question, description, ponderation, position, type, level, extra
)
VALUES (
'$course_id',
'" . Database::escape_string($question) . "',
'" . Database::escape_string($description) . "',
'" . Database::escape_string($weighting) . "',
'" . Database::escape_string($position) . "',
'" . Database::escape_string($type) . "',
'" . Database::escape_string($level) . "',
'" . Database::escape_string($extra) . "'
)";
Database::query($sql);
$new_question_id = Database::insert_id();
@ -1267,7 +1382,6 @@ abstract class Question
document.getElementById ( \'HiddenFCK\' + editorInstanceName ).className = "media";
}
}
</script>';
// question name
@ -1458,7 +1572,7 @@ abstract class Question
echo Display::return_icon('database_na.png', get_lang('GetExistingQuestion'), null, ICON_SIZE_BIG);
} else {
if ($feedback_type == 1) {
echo $url = '<a href="question_pool.php?'.api_get_cidreq().'&type=1&fromExercise='.$exerciseId.'">';
echo $url = "<a href=\"question_pool.php?" . api_get_cidreq() . "&type=1&fromExercise=$exerciseId\">";
} else {
echo $url = '<a href="question_pool.php?' . api_get_cidreq() . '&fromExercise=' . $exerciseId . '">';
}
@ -1598,7 +1712,10 @@ abstract class Question
}
$header .= Display::page_subheader2($counter_label . ". " . $question_title);
$header .= Display::div('<div class="rib rib-'.$class.'"><h3>'.$score_label.'</h3></div> <h4>'.$score['result'].' </h4>', array('class'=>'ribbon'));
$header .= Display::div(
"<div class=\"rib rib-$class\"><h3>$score_label'</h3></div> <h4>{$score['result']}</h4>",
array('class' => 'ribbon')
);
$header .= Display::div($this->description, array('id' => 'question_description'));
return $header;
}
@ -1642,8 +1759,18 @@ abstract class Question
$max_position = $row_max->max_position + 1;
// Insert the new question
$sql = "INSERT INTO $tbl_quiz_question (c_id, question, description, ponderation, position, type, level)
VALUES ($course_id, '".Database::escape_string($question_name)."', '".Database::escape_string($question_description)."', '$max_score', $max_position, $type, $level)";
$sql = "INSERT INTO $tbl_quiz_question (
c_id, question, description, ponderation, position, type, level
)
VALUES (
$course_id,
'" . Database::escape_string($question_name) . "',
'" . Database::escape_string($question_description) . "',
'$max_score',
$max_position,
$type,
$level
)";
Database::query($sql);
// Get the question ID
@ -1687,15 +1814,25 @@ abstract class Question
* Get course medias
* @param int course id
*/
static function get_course_medias($course_id, $start = 0, $limit = 100, $sidx = "question", $sord = "ASC", $where_condition = array())
static function get_course_medias(
$course_id,
$start = 0,
$limit = 100,
$sidx = "question",
$sord = "ASC",
$where_condition = array()
)
{
$table_question = Database::get_course_table(TABLE_QUIZ_QUESTION);
$default_where = array('c_id = ? AND parent_id = 0 AND type = ?' => array($course_id, MEDIA_QUESTION));
$result = Database::select('*', $table_question,
$result = Database::select(
'*',
$table_question,
array(
'limit' => " $start, $limit",
'where' => $default_where,
'order' => "$sidx $sord")
'order' => "$sidx $sord"
)
);
return $result;
}

@ -100,7 +100,7 @@ $ajax_url = api_get_path(WEB_AJAX_PATH)."exercise.ajax.php?".api_get_cidreq()."&
$( "#question_list" ).accordion({
icons: icons,
autoHeight: false,
heightStyle: "content",
active: false, // all items closed by default
collapsible: true,
header: ".header_operations"

@ -472,6 +472,7 @@ define('ORAL_EXPRESSION', 13);
define('GLOBAL_MULTIPLE_ANSWER', 14);
define('MEDIA_QUESTION', 15);
define('CALCULATED_ANSWER', 16);
define('UNIQUE_ANSWER_IMAGE', 17);
//Some alias used in the QTI exports
define('MCUA', 1);

@ -82,7 +82,8 @@ class ExerciseLib
return '';
}
echo '<div class="question_options">';
echo '<div class="question_options row">';
// construction of the Answer object (also gets all answers details)
$objAnswerTmp = new Answer($questionId);
@ -104,7 +105,7 @@ class ExerciseLib
$num_suggestions = 0;
if ($answerType == MATCHING) {
$s .= '<table class="data_table">';
$s .= '<table class="table table-hover table-striped">';
// Iterate through answers
$x = 1;
//mark letters for each answer
@ -213,7 +214,7 @@ class ExerciseLib
if ($show_comment) {
$header .= Display::tag('th', get_lang('Feedback'));
}
$s .= '<table class="data_table">';
$s .= '<table class="table table-hover table-striped">';
$s .= Display::tag(
'tr',
$header,
@ -222,12 +223,14 @@ class ExerciseLib
}
if ($show_comment) {
if (in_array(
if (
in_array(
$answerType,
array(
MULTIPLE_ANSWER,
MULTIPLE_ANSWER_COMBINATION,
UNIQUE_ANSWER,
UNIQUE_ANSWER_IMAGE,
UNIQUE_ANSWER_NO_OPTION,
GLOBAL_MULTIPLE_ANSWER
)
@ -237,7 +240,7 @@ class ExerciseLib
if ($exercise_feedback == EXERCISE_FEEDBACK_TYPE_END) {
$header .= Display::tag('th', get_lang('Feedback'));
}
$s .= '<table class="data_table">';
$s .= '<table class="table table-hover table-striped">';
$s .= Display::tag(
'tr',
$header,
@ -263,7 +266,7 @@ class ExerciseLib
$attributes = array();
// Unique answer
if ($answerType == UNIQUE_ANSWER || $answerType == UNIQUE_ANSWER_NO_OPTION) {
if (in_array($answerType, [UNIQUE_ANSWER, UNIQUE_ANSWER_NO_OPTION, UNIQUE_ANSWER_IMAGE])) {
$input_id = 'choice-' . $questionId . '-' . $answerId;
if (isset($user_choice[0]['answer']) && $user_choice[0]['answer'] == $numAnswer) {
$attributes = array(
@ -282,6 +285,25 @@ class ExerciseLib
}
}
if ($show_comment) {
$s .= '<tr><td>';
}
if ($answerType == UNIQUE_ANSWER_IMAGE) {
if ($show_comment) {
if (empty($comment)) {
$s .= '<div id="answer' . $questionId . $numAnswer . '" '
. 'class="exercise-unique-answer-image col-xs-6" style="text-align: center">';
} else {
$s .= '<div id="answer' . $questionId . $numAnswer . '" '
. 'class="exercise-unique-answer-image col-xs-6 col-sm-12" style="text-align: center">';
}
} else {
$s .= '<div id="answer' . $questionId . $numAnswer . '" '
. 'class="exercise-unique-answer-image col-xs-6 col-md-4" style="text-align: center">';
}
}
$answer = Security::remove_XSS($answer, STUDENT);
$s .= Display::input(
'hidden',
@ -289,7 +311,15 @@ class ExerciseLib
'0'
);
$answer_input = '<label class="radio">';
$answer_input = null;
if ($answerType == UNIQUE_ANSWER_IMAGE) {
$attributes['style'] = 'display: none;';
$answer = '<div class="thumbnail">' . $answer . '</div>';
}
$answer_input .= '<label class="radio">';
$answer_input .= Display::input(
'radio',
'choice[' . $questionId . ']',
@ -299,8 +329,11 @@ class ExerciseLib
$answer_input .= $answer;
$answer_input .= '</label>';
if ($answerType == UNIQUE_ANSWER_IMAGE) {
$answer_input .= "</div>";
}
if ($show_comment) {
$s .= '<tr><td>';
$s .= $answer_input;
$s .= '</td>';
$s .= '<td>';
@ -311,7 +344,8 @@ class ExerciseLib
$s .= $answer_input;
}
} elseif ($answerType == MULTIPLE_ANSWER ||
} elseif (
$answerType == MULTIPLE_ANSWER ||
$answerType == MULTIPLE_ANSWER_TRUE_FALSE ||
$answerType == GLOBAL_MULTIPLE_ANSWER
) {

@ -7084,4 +7084,5 @@ $BadgesManagement = "Badges management";
$CurrentBadges = "Current badges";
$SaveBadge = "Save badge";
$BadgeMeasuresXPixelsInPNG = "Badge measures 200x200 pixels in PNG";
$UniqueAnswerImage = "Unique answer image";
?>

@ -6826,7 +6826,7 @@ $NumberOfPublishedExercises = "Nro de ejercicios publicados";
$NumberOfPublishedLps = "Nro de Lecciones publicadas";
$ChatConnected = "Chat (Conectado)";
$ChatDisconnected = "Chat (Desconectado)";
$AddCourseDescription = "Agregar descripción del curso";
$AddCourseDescription = "Describir el curso";
$ThingsToDo = "Primeras actividades sugeridas";
$RecordAnswer = "Grabar respuesta";
$UseTheMessageBelowToAddSomeComments = "Utilizar el siguiente campo de texto para escribir un comentario al profesor";
@ -7100,6 +7100,9 @@ $WorkEmailAlertActivateOnlyForTeachers = "Activar sólo para profesores el aviso
$WorkEmailAlertActivateOnlyForStudents = "Activar sólo para alumnos el aviso por correo electrónico del envío de una nueva tarea";
$Uncategorized = "Sin categoría";
$NaturalYear = "Año natural";
$AutoWeight = "Auto-ponderación";
$AutoWeightExplanation = "La ponderación automática permite ganar algo de tiempo. Esta funcionalidad distribuirá el peso total entre los elementos a bajo de manera equilibrada.";
$EditWeight = "Editar ponderación";
$TheSkillHasBeenCreated = "La competencia ha sido creada";
$CreateSkill = "Crear competencia";
$CannotCreateSkill = "No se puede crear la competencia";
@ -7110,4 +7113,6 @@ $BadgesManagement = "Gestionar las insignias";
$CurrentBadges = "Insignias actuales";
$SaveBadge = "Guardar insignia";
$BadgeMeasuresXPixelsInPNG = "Medidas de la insignia 200x200 píxeles en formato PNG";
$SetTutor = "Hacer tutor";
$UniqueAnswerImage = "Respuesta de imagen única";
?>
Loading…
Cancel
Save