Fix sequence ordering see #7846

1.10.x
Julio Montoya 9 years ago
parent 16620dab75
commit 4b043729c3
  1. 13
      main/exercice/answer.class.php
  2. 20
      main/exercice/exercise.class.php
  3. 6
      main/exercice/exercise_submit.php
  4. 18
      main/inc/lib/exercise.lib.php
  5. 10
      main/inc/lib/template.lib.php
  6. 440
      main/template/default/exercise/submit.js.tpl

@ -206,7 +206,14 @@ class Answer
$sql = "SELECT type FROM $TBL_QUIZ $sql = "SELECT type FROM $TBL_QUIZ
WHERE c_id = {$this->course_id} AND id = $questionId"; WHERE c_id = {$this->course_id} AND id = $questionId";
$result_question = Database::query($sql); $result_question = Database::query($sql);
$question_type = Database::fetch_array($result_question); $questionType = Database::fetch_array($result_question);
if ($questionType['type'] == DRAGGABLE) {
// Random is done by submit.js.tpl
$this->read();
return true;
}
$sql = "SELECT $sql = "SELECT
answer, answer,
@ -229,7 +236,7 @@ class Answer
// while a record is found // while a record is found
$doubt_data = null; $doubt_data = null;
while ($object = Database::fetch_object($result)) { while ($object = Database::fetch_object($result)) {
if ($question_type['type'] == UNIQUE_ANSWER_NO_OPTION && $object->position == 666) { if ($questionType['type'] == UNIQUE_ANSWER_NO_OPTION && $object->position == 666) {
$doubt_data = $object; $doubt_data = $object;
continue; continue;
} }
@ -243,7 +250,7 @@ class Answer
$i++; $i++;
} }
if ($question_type['type'] == UNIQUE_ANSWER_NO_OPTION && !empty($doubt_data)) { if ($questionType['type'] == UNIQUE_ANSWER_NO_OPTION && !empty($doubt_data)) {
$this->answer[$i] = $doubt_data->answer; $this->answer[$i] = $doubt_data->answer;
$this->correct[$i] = $doubt_data->correct; $this->correct[$i] = $doubt_data->correct;
$this->comment[$i] = $doubt_data->comment; $this->comment[$i] = $doubt_data->comment;

@ -2866,6 +2866,7 @@ class Exercise
exe_id = '$exeId' AND exe_id = '$exeId' AND
question_id = '$questionId' AND question_id = '$questionId' AND
position = '$i_answer_id_auto'"; position = '$i_answer_id_auto'";
$res_user_answer = Database::query($sql); $res_user_answer = Database::query($sql);
if (Database::num_rows($res_user_answer) > 0) { if (Database::num_rows($res_user_answer) > 0) {
@ -2879,19 +2880,22 @@ class Exercise
$user_answer = ''; $user_answer = '';
if (!empty($s_user_answer)) { if (!empty($s_user_answer)) {
if ($s_user_answer == $i_answer_correct_answer) { if ($answerType == DRAGGABLE) {
$questionScore += $i_answerWeighting; if ($s_user_answer == $i_answer_correct_answer) {
$totalScore += $i_answerWeighting; $questionScore += $i_answerWeighting;
if ($answerType == DRAGGABLE) { $totalScore += $i_answerWeighting;
$user_answer = Display::label(get_lang('Correct'), 'success'); $user_answer = Display::label(get_lang('Correct'), 'success');
} else { } else {
$user_answer = Display::label(get_lang('Incorrect'), 'danger');
}
} else {
if ($s_user_answer == $i_answer_correct_answer) {
$questionScore += $i_answerWeighting;
$totalScore += $i_answerWeighting;
if (isset($real_list[$i_answer_id])) { if (isset($real_list[$i_answer_id])) {
$user_answer = Display::span($real_list[$i_answer_id]); $user_answer = Display::span($real_list[$i_answer_id]);
} }
}
} else {
if ($answerType == DRAGGABLE) {
$user_answer = Display::label(get_lang('Incorrect'), 'danger');
} else { } else {
$user_answer = Display::span( $user_answer = Display::span(
$real_list[$s_user_answer], $real_list[$s_user_answer],

@ -62,8 +62,6 @@ $htmlHeadXtra[] = api_get_js('epiclock/renderers/minute/epiclock.minute.js');
$template = new Template(); $template = new Template();
$htmlHeadXtra[] = $template->fetch('default/exercise/submit.js.tpl');
// General parameters passed via POST/GET // General parameters passed via POST/GET
$learnpath_id = isset($_REQUEST['learnpath_id']) ? intval($_REQUEST['learnpath_id']) : 0; $learnpath_id = isset($_REQUEST['learnpath_id']) ? intval($_REQUEST['learnpath_id']) : 0;
@ -94,7 +92,7 @@ $exercise_attempt_table = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATT
/* Teacher takes an exam and want to see a preview, /* Teacher takes an exam and want to see a preview,
we delete the objExercise from the session in order to get the latest we delete the objExercise from the session in order to get the latest
changes in the exercise */ changes in the exercise */
if (api_is_allowed_to_edit(null,true) && isset($_GET['preview']) && $_GET['preview'] == 1 ) { if (api_is_allowed_to_edit(null, true) && isset($_GET['preview']) && $_GET['preview'] == 1 ) {
Session::erase('objExercise'); Session::erase('objExercise');
} }
@ -145,6 +143,8 @@ if ($objExercise->review_answers) {
exit; exit;
} }
} }
$template->assign('shuffle_answers', $objExercise->random_answers);
$htmlHeadXtra[] = $template->fetch('default/exercise/submit.js.tpl');
$current_timestamp = time(); $current_timestamp = time();
$my_remind_list = array(); $my_remind_list = array();

@ -39,6 +39,7 @@ class ExerciseLib
$exercise_feedback = null, $exercise_feedback = null,
$show_answers = false $show_answers = false
) { ) {
$course_id = api_get_course_int_id();
// Change false to true in the following line to enable answer hinting // Change false to true in the following line to enable answer hinting
$debug_mark_answer = $show_answers; $debug_mark_answer = $show_answers;
@ -86,9 +87,8 @@ class ExerciseLib
// construction of the Answer object (also gets all answers details) // construction of the Answer object (also gets all answers details)
$objAnswerTmp = new Answer($questionId); $objAnswerTmp = new Answer($questionId);
$nbrAnswers = $objAnswerTmp->selectNbrAnswers(); $nbrAnswers = $objAnswerTmp->selectNbrAnswers();
$course_id = api_get_course_int_id();
$quiz_question_options = Question::readQuestionOption( $quiz_question_options = Question::readQuestionOption(
$questionId, $questionId,
$course_id $course_id
@ -124,8 +124,6 @@ HTML;
for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) { for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) {
$answerCorrect = $objAnswerTmp->isCorrect($answerId); $answerCorrect = $objAnswerTmp->isCorrect($answerId);
$numAnswer = $objAnswerTmp->selectAutoId($answerId); $numAnswer = $objAnswerTmp->selectAutoId($answerId);
$answer = $objAnswerTmp->selectAnswer($answerId);
if ($answerCorrect == 0) { if ($answerCorrect == 0) {
// options (A, B, C, ...) that will be put into the list-box // options (A, B, C, ...) that will be put into the list-box
// have the "correct" field set to 0 because they are answer // have the "correct" field set to 0 because they are answer
@ -631,7 +629,8 @@ HTML;
$trackAttempts = Database::get_main_table( $trackAttempts = Database::get_main_table(
TABLE_STATISTIC_TRACK_E_ATTEMPT TABLE_STATISTIC_TRACK_E_ATTEMPT
); );
$sqlTrackAttempt = 'SELECT answer FROM ' . $trackAttempts . ' WHERE exe_id=' . $exe_id . ' AND question_id=' . $questionId; $sqlTrackAttempt = 'SELECT answer FROM ' . $trackAttempts . '
WHERE exe_id=' . $exe_id . ' AND question_id=' . $questionId;
$rsLastAttempt = Database::query($sqlTrackAttempt); $rsLastAttempt = Database::query($sqlTrackAttempt);
$rowLastAttempt = Database::fetch_array($rsLastAttempt); $rowLastAttempt = Database::fetch_array($rsLastAttempt);
$answer = $rowLastAttempt['answer']; $answer = $rowLastAttempt['answer'];
@ -789,9 +788,6 @@ HTML;
if (isset($user_choice_array_position[$numAnswer]) && $val['id'] == $user_choice_array_position[$numAnswer]) { if (isset($user_choice_array_position[$numAnswer]) && $val['id'] == $user_choice_array_position[$numAnswer]) {
$selected = 'selected="selected"'; $selected = 'selected="selected"';
} }
/*if (isset($user_choice_array[$matching_correct_answer]) && $val['id'] == $user_choice_array[$matching_correct_answer]['answer']) {
$selected = 'selected="selected"';
}*/
$s .= '<option value="' . $val['id'] . '" ' . $selected . '>' . $val['letter'] . '</option>'; $s .= '<option value="' . $val['id'] . '" ' . $selected . '>' . $val['letter'] . '</option>';
} // end foreach() } // end foreach()
@ -825,6 +821,11 @@ HTML;
} elseif ($answerType == DRAGGABLE) { } elseif ($answerType == DRAGGABLE) {
if ($answerCorrect != 0) { if ($answerCorrect != 0) {
$parsed_answer = $answer; $parsed_answer = $answer;
/*$lines_count = '';
$data = $objAnswerTmp->getAnswerByAutoId($numAnswer);
$data = $objAnswerTmp->getAnswerByAutoId($data['correct']);
$lines_count = $data['answer'];*/
$windowId = $questionId . '_' . $lines_count; $windowId = $questionId . '_' . $lines_count;
$s .= '<li class="touch-items" id="' . $windowId . '">'; $s .= '<li class="touch-items" id="' . $windowId . '">';
@ -901,7 +902,6 @@ JAVASCRIPT;
while (isset($select_items[$lines_count])) { while (isset($select_items[$lines_count])) {
$s .= Display::tag('b', $select_items[$lines_count]['letter']); $s .= Display::tag('b', $select_items[$lines_count]['letter']);
$s .= $select_items[$lines_count]['answer']; $s .= $select_items[$lines_count]['answer'];
$lines_count++; $lines_count++;
} }
} }

@ -614,7 +614,7 @@ class Template
public function set_js_files() public function set_js_files()
{ {
global $disable_js_and_css_files, $htmlHeadXtra; global $disable_js_and_css_files, $htmlHeadXtra;
$isoCode = api_get_language_isocode(); $isoCode = api_get_language_isocode();
//JS files //JS files
@ -1092,12 +1092,12 @@ class Template
} }
/** /**
* @param $tpl_var * @param string $variable
* @param null $value * @param mixed $value
*/ */
public function assign($tpl_var, $value = null) public function assign($variable, $value = '')
{ {
$this->params[$tpl_var] = $value; $this->params[$variable] = $value;
} }
/** /**

@ -1,243 +1,267 @@
<script> <script>
var DraggableAnswer = {
gallery: null,
trash: null,
deleteItem: function (item, insertHere) {
if (insertHere.find(".exercise-draggable-answer-option").length > 0) {
return false;
}
item.fadeOut(function () { var DraggableAnswer = {
var $list = $('<div class="gallery ui-helper-reset"/>').appendTo(insertHere); gallery: null,
trash: null,
deleteItem: function (item, insertHere) {
if (insertHere.find(".exercise-draggable-answer-option").length > 0) {
return false;
}
item.find('a.btn').remove(); item.fadeOut(function () {
var $list = $('<div class="gallery ui-helper-reset"/>').appendTo(insertHere);
var droppedId = item.attr('id'), item.find('a.btn').remove();
dropedOnId = insertHere.attr('id'),
originSelectId = 'window_' + droppedId + '_select',
value = dropedOnId.split('_')[2];
$('#' + originSelectId + ' option') var droppedId = item.attr('id'),
.filter(function (index) { dropedOnId = insertHere.attr('id'),
return index === parseInt(value); originSelectId = 'window_' + droppedId + '_select',
}) value = dropedOnId.split('_')[2];
.attr("selected", true);
$('#' + originSelectId + ' option')
var recycleButton = $('<a>') .filter(function (index) {
.attr('href', '#') return index === parseInt(value);
.addClass('btn btn-default btn-xs') })
.append( .attr("selected", true);
"{{ "Undo" | get_lang }} ",
$('<i>').addClass('fa fa-undo') var recycleButton = $('<a>')
) .attr('href', '#')
.on('click', function (e) { .addClass('btn btn-default btn-xs')
e.preventDefault(); .append(
"{{ "Undo" | get_lang }} ",
$('<i>').addClass('fa fa-undo')
)
.on('click', function (e) {
e.preventDefault();
var liParent = $(this).parent();
DraggableAnswer.recycleItem(liParent);
});
var liParent = $(this).parent(); item.append(recycleButton).appendTo($list).fadeIn();
});
},
recycleItem: function (item) {
item.fadeOut(function () {
item
.find('a.btn')
.remove()
.end()
.find("img")
.end()
.appendTo(DraggableAnswer.gallery)
.fadeIn();
});
var droppedId = item.attr('id'),
originSelectId = 'window_' + droppedId + '_select';
$('#' + originSelectId + ' option:first').attr('selected', 'selected');
},
init: function (gallery, trash) {
this.gallery = gallery;
this.trash = trash;
$("li", DraggableAnswer.gallery).draggable({
cancel: "a.ui-icon",
revert: "invalid",
containment: "document",
helper: "clone",
cursor: "move"
});
DraggableAnswer.trash.droppable({
accept: ".exercise-draggable-answer > li",
hoverClass: "ui-state-active",
drop: function (e, ui) {
DraggableAnswer.deleteItem(ui.draggable, $(this));
}
});
DraggableAnswer.recycleItem(liParent); DraggableAnswer.gallery.droppable({
}); drop: function (e, ui) {
DraggableAnswer.recycleItem(ui.draggable, $(this));
}
});
}
};
var MatchingDraggable = {
colorDestination: '#316B31',
curviness: 0,
connectorType: 'Straight',
initialized: false,
init: function (questionId) {
var windowQuestionSelector = '.window' + questionId + '_question',
countConnections = $(windowQuestionSelector).length,
colorArray = [],
colorArrayDestination = [];
if (countConnections > 0) {
colorArray = $.xcolor.analogous("#da0", countConnections);
colorArrayDestination = $.xcolor.analogous("#51a351", countConnections);
} else {
colorArray = $.xcolor.analogous("#da0", 10);
colorArrayDestination = $.xcolor.analogous("#51a351", 10);
}
item.append(recycleButton).appendTo($list).fadeIn(); jsPlumb.importDefaults({
}); DragOptions: {cursor: 'pointer', zIndex: 2000},
}, PaintStyle: {strokeStyle: '#000'},
recycleItem: function (item) { EndpointStyle: {strokeStyle: '#316b31'},
item.fadeOut(function () { Endpoint: 'Rectangle',
item Anchors: ['TopCenter', 'TopCenter']
.find('a.btn') });
.remove()
.end() var exampleDropOptions = {
.find("img") tolerance: 'touch',
.end() hoverClass: 'dropHover',
.appendTo(DraggableAnswer.gallery) activeClass: 'dragActive'
.fadeIn(); };
});
var destinationEndPoint = {
endpoint: ["Dot", {radius: 15}],
paintStyle: {fillStyle: MatchingDraggable.colorDestination},
isSource: false,
connectorStyle: {strokeStyle: MatchingDraggable.colorDestination, lineWidth: 8},
connector: [
MatchingDraggable.connectorType,
{curviness: MatchingDraggable.curviness}
],
maxConnections: 1000,
isTarget: true,
dropOptions: exampleDropOptions,
beforeDrop: function (params) {
jsPlumb.select({source: params.sourceId}).each(function (connection) {
jsPlumb.detach(connection);
});
var droppedId = item.attr('id'), var selectId = params.sourceId + "_select";
originSelectId = 'window_' + droppedId + '_select'; var value = params.targetId.split("_")[2];
$('#' + originSelectId + ' option:first').attr('selected', 'selected');
},
init: function (gallery, trash) {
this.gallery = gallery;
this.trash = trash;
$("li", DraggableAnswer.gallery).draggable({
cancel: "a.ui-icon",
revert: "invalid",
containment: "document",
helper: "clone",
cursor: "move"
});
DraggableAnswer.trash.droppable({ $("#" + selectId + " option")
accept: ".exercise-draggable-answer > li", .removeAttr('selected')
hoverClass: "ui-state-active", .filter(function (index) {
drop: function (e, ui) { return index === parseInt(value);
DraggableAnswer.deleteItem(ui.draggable, $(this)); })
} .attr("selected", true);
});
DraggableAnswer.gallery.droppable({ return true;
drop: function (e, ui) {
DraggableAnswer.recycleItem(ui.draggable, $(this));
}
});
}
};
var MatchingDraggable = {
colorDestination: '#316B31',
curviness: 0,
connectorType: 'Straight',
initialized: false,
init: function (questionId) {
var windowQuestionSelector = '.window' + questionId + '_question',
countConnections = $(windowQuestionSelector).length,
colorArray = [],
colorArrayDestination = [];
if (countConnections > 0) {
colorArray = $.xcolor.analogous("#da0", countConnections);
colorArrayDestination = $.xcolor.analogous("#51a351", countConnections);
} else {
colorArray = $.xcolor.analogous("#da0", 10);
colorArrayDestination = $.xcolor.analogous("#51a351", 10);
} }
};
jsPlumb.importDefaults({ var count = 0;
DragOptions: {cursor: 'pointer', zIndex: 2000}, var sourceDestinationArray = [];
PaintStyle: {strokeStyle: '#000'},
EndpointStyle: {strokeStyle: '#316b31'},
Endpoint: 'Rectangle',
Anchors: ['TopCenter', 'TopCenter']
});
var exampleDropOptions = { $(windowQuestionSelector).each(function (index) {
tolerance: 'touch', var windowId = $(this).attr("id");
hoverClass: 'dropHover', var scope = windowId + "scope";
activeClass: 'dragActive' var destinationColor = colorArray[count].getHex();
};
var destinationEndPoint = { var sourceEndPoint = {
endpoint: ["Dot", {radius: 15}], endpoint: [
paintStyle: {fillStyle: MatchingDraggable.colorDestination}, "Dot",
isSource: false, {radius: 15}
connectorStyle: {strokeStyle: MatchingDraggable.colorDestination, lineWidth: 8}, ],
paintStyle: {
fillStyle: destinationColor
},
isSource: true,
connectorStyle: {
strokeStyle: "#8a8888",
lineWidth: 8
},
connector: [ connector: [
MatchingDraggable.connectorType, MatchingDraggable.connectorType,
{curviness: MatchingDraggable.curviness} {curviness: MatchingDraggable.curviness}
], ],
maxConnections: 1000, maxConnections: 1,
isTarget: true, isTarget: false,
dropOptions: exampleDropOptions, dropOptions: exampleDropOptions,
beforeDrop: function (params) { scope: scope
jsPlumb.select({source: params.sourceId}).each(function (connection) { };
jsPlumb.detach(connection);
});
var selectId = params.sourceId + "_select"; sourceDestinationArray[count + 1] = sourceEndPoint;
var value = params.targetId.split("_")[2];
$("#" + selectId + " option") count++;
.removeAttr('selected')
.filter(function (index) {
return index === parseInt(value);
})
.attr("selected", true);
return true; jsPlumb.addEndpoint(
} windowId,
}; {
anchor: ['RightMiddle', 'RightMiddle', 'RightMiddle', 'RightMiddle']
},
sourceEndPoint
);
var count = 0; var destinationCount = 0;
var sourceDestinationArray = [];
$(windowQuestionSelector).each(function (index) { $(windowQuestionSelector).each(function (index) {
var windowId = $(this).attr("id"); var windowDestinationId = $(this).attr("id");
var scope = windowId + "scope"; destinationEndPoint.scope = scope;
var destinationColor = colorArray[count].getHex(); destinationEndPoint.paintStyle.fillStyle = colorArrayDestination[destinationCount].getHex();
destinationCount++;
var sourceEndPoint = {
endpoint: [
"Dot",
{radius: 15}
],
paintStyle: {
fillStyle: destinationColor
},
isSource: true,
connectorStyle: {
strokeStyle: "#8a8888",
lineWidth: 8
},
connector: [
MatchingDraggable.connectorType,
{curviness: MatchingDraggable.curviness}
],
maxConnections: 1,
isTarget: false,
dropOptions: exampleDropOptions,
scope: scope
};
sourceDestinationArray[count + 1] = sourceEndPoint;
count++;
jsPlumb.addEndpoint( jsPlumb.addEndpoint(
windowId, windowDestinationId + "_answer",
{ {
anchor: ['RightMiddle', 'RightMiddle', 'RightMiddle', 'RightMiddle'] anchors: ['LeftMiddle', 'LeftMiddle', 'LeftMiddle', 'LeftMiddle']
}, },
sourceEndPoint destinationEndPoint
); );
var destinationCount = 0;
$(windowQuestionSelector).each(function (index) {
var windowDestinationId = $(this).attr("id");
destinationEndPoint.scope = scope;
destinationEndPoint.paintStyle.fillStyle = colorArrayDestination[destinationCount].getHex();
destinationCount++;
jsPlumb.addEndpoint(
windowDestinationId + "_answer",
{
anchors: ['LeftMiddle', 'LeftMiddle', 'LeftMiddle', 'LeftMiddle']
},
destinationEndPoint
);
});
}); });
});
MatchingDraggable.attachBehaviour(); MatchingDraggable.attachBehaviour();
}, },
attachBehaviour: function () { attachBehaviour: function () {
if (!MatchingDraggable.initialized) { if (!MatchingDraggable.initialized) {
MatchingDraggable.initialized = true; MatchingDraggable.initialized = true;
}
}
};
jsPlumb.ready(function () {
if ($(".drag_question").length > 0) {
MatchingDraggable.init();
$(document).scroll(function () {
jsPlumb.repaintEverything();
});
$(window).resize(function () {
jsPlumb.repaintEverything();
});
} }
}); }
};
$(document).on('ready', function () {
DraggableAnswer.init( jsPlumb.ready(function () {
$(".exercise-draggable-answer"), if ($(".drag_question").length > 0) {
$(".droppable") MatchingDraggable.init();
);
}); $(document).scroll(function () {
jsPlumb.repaintEverything();
});
$(window).resize(function () {
jsPlumb.repaintEverything();
});
}
});
$(document).on('ready', function () {
DraggableAnswer.init(
$(".exercise-draggable-answer"),
$(".droppable")
);
// if shuffle answers
if ('{{ shuffle_answers }}' == '1') {
$('.exercise-draggable-answer').each(function(){
// get current ul
var $ul = $(this);
// get array of list items in current ul
var $liArr = $ul.children('li');
// sort array of list items in current ul randomly
$liArr.sort(function(a,b){
// Get a random number between 0 and 10
var temp = parseInt( Math.random()*100 );
// Get 1 or 0, whether temp is odd or even
var isOddOrEven = temp%2;
// Get +1 or -1, whether temp greater or smaller than 5
var isPosOrNeg = temp>5 ? 1 : -1;
// Return -1, 0, or +1
return( isOddOrEven*isPosOrNeg );
})
// append list items to ul
.appendTo($ul);
});
}
});
</script> </script>

Loading…
Cancel
Save