diff --git a/question/type/ordering/edit_ordering_form.php b/question/type/ordering/edit_ordering_form.php
index 772826653da..247da49a1ee 100644
--- a/question/type/ordering/edit_ordering_form.php
+++ b/question/type/ordering/edit_ordering_form.php
@@ -34,6 +34,11 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_ordering_edit_form extends question_edit_form {
+
+ public function qtype() {
+ return 'ordering';
+ }
+
/**
* Add question-type specific form fields.
*
@@ -43,28 +48,35 @@ class qtype_ordering_edit_form extends question_edit_form {
$NUMANS_START = 10;
$NUMANS_ADD = 5;
- $menu = array(get_string('ordering_exactorder', 'qtype_ordering'), get_string('ordering_relativeorder', 'qtype_ordering'), get_string('ordering_contiguous', 'qtype_ordering'));
- $mform->addElement('select', 'logical', get_string('ordering_logicalpossibilities', 'qtype_ordering'), $menu);
+ $options = array(
+ 0 => get_string('ordering_exactorder', 'qtype_ordering'), // = all ?
+ 1 => get_string('ordering_relativeorder', 'qtype_ordering'), // = random subset
+ 2 => get_string('ordering_contiguous', 'qtype_ordering') // = contiguous subset
+ );
+ $mform->addElement('select', 'logical', get_string('ordering_logicalpossibilities', 'qtype_ordering'), $options);
$mform->setDefault('logical', 0);
- $menu1[] = "All";
+ $options = array(0 => 'All');
for ($i=3; $i <= 20; $i++) {
- $menu1[] = $i;
+ $options[] = $i;
}
- $mform->addElement('select', 'studentsee', get_string('ordering_itemsforstudent', 'qtype_ordering'), $menu1);
+ $mform->addElement('select', 'studentsee', get_string('ordering_itemsforstudent', 'qtype_ordering'), $options);
$mform->setDefault('studentsee', 0);
$repeated = array();
$repeated[] =& $mform->createElement('header', 'choicehdr', get_string('ordering_choiceno', 'qtype_ordering', '{no}'));
$repeated[] =& $mform->createElement('textarea', 'answer', get_string('ordering_answer', 'qtype_ordering'), 'rows="3" cols="50"');
- if (isset($this->question->options)){
- $countanswers = count($this->question->options->answers);
- } else {
+ if (empty($this->question->options)){
$countanswers = 0;
+ } else {
+ $countanswers = count($this->question->options->answers);
+ }
+ if ($NUMANS_START > ($countanswers + $NUMANS_ADD)) {
+ $repeatsatstart = $NUMANS_START;
+ } else {
+ $repeatsatstart = ($countanswers + $NUMANS_ADD);
}
- $repeatsatstart = ($NUMANS_START > ($countanswers + $NUMANS_ADD))?
- $NUMANS_START : ($countanswers + $NUMANS_ADD);
$repeatedoptions = array();
$repeatedoptions['fraction']['default'] = 0;
$mform->setType('answer', PARAM_NOTAGS);
@@ -109,27 +121,16 @@ class qtype_ordering_edit_form extends question_edit_form {
}
- //echo "data_preprocessing";
- //print_r ($question);
- //die();
-
return $question;
-
- //return true;
}
public function validation($data, $files) {
$errors = array();
- $answers = $data['answer'];
+
$answercount = 0;
-
- $totalfraction = 0;
- $maxfraction = -1;
-
- foreach ($answers as $key => $answer){
- //check no of choices
- $trimmedanswer = trim($answer);
- if (!empty($trimmedanswer)){
+ foreach ($data['answer'] as $answer){
+ $answer = trim($answer);
+ if ($answer || $answer==='0'){
$answercount++;
}
}
@@ -144,8 +145,4 @@ class qtype_ordering_edit_form extends question_edit_form {
return $errors;
}
-
- public function qtype() {
- return 'ordering';
- }
}
diff --git a/question/type/ordering/question.php b/question/type/ordering/question.php
index 19f451844ed..05f7366314a 100644
--- a/question/type/ordering/question.php
+++ b/question/type/ordering/question.php
@@ -15,7 +15,7 @@
// along with Moodle. If not, see
';
- //print_r ($answer);
- if (!$answer->id = $DB->insert_record("question_answers", $answer)) {
- $result->error = "Could not insert quiz answer! ";
- return $result;
- }
+ if ($answer->id = array_shift($answerids)) {
+ if (! $DB->update_record('question_answers', $answer)) {
+ $result->error = 'Could not update quiz answer! (id='.$answer->id.')';
+ return $result;
}
- $answers[] = $answer->id;
-
- if ($question->fraction[$key] > 0) { // Sanity checks
- $totalfraction += $question->fraction[$key];
- }
- if ($question->fraction[$key] > $maxfraction) {
- $maxfraction = $question->fraction[$key];
+ } else {
+ if (! $answer->id = $DB->insert_record('question_answers', $answer)) {
+ $result->error = 'Could not insert quiz answer! ';
+ return $result;
}
}
}
- $update = true;
- $options = $DB->get_record("question_ordering", array("question" => $question->id));
- if (!$options) {
- $update = false;
- $options = new stdClass;
- $options->question = $question->id;
+ // create $options for this ordering question
+ $options = (object)array(
+ 'question' => $question->id,
+ 'logical' => $question->logical,
+ 'studentsee' => $question->studentsee,
+ 'correctfeedback' => $question->correctfeedback,
+ 'incorrectfeedback' => $question->incorrectfeedback,
+ 'partiallycorrectfeedback' => $question->partiallycorrectfeedback
+ );
- }
- $options->logical = $question->logical;
- $options->studentsee = $question->studentsee;
- $options->correctfeedback = $question->correctfeedback;
- $options->partiallycorrectfeedback = $question->partiallycorrectfeedback;
- $options->incorrectfeedback = $question->incorrectfeedback;
-
- if ($update) {
- if (!$DB->update_record("question_ordering", $options)) {
- $result->error = "Could not update quiz ordering options! (id=$options->id)";
+ // add/update $options for this ordering question
+ if ($options->id = $DB->get_field('question_ordering', 'id', array('question' => $question->id))) {
+ if (! $DB->update_record('question_ordering', $options)) {
+ $result->error = 'Could not update quiz ordering options! (id='.$options->id.')';
return $result;
}
} else {
- if (!$DB->insert_record("question_ordering", $options)) {
- $result->error = "Could not insert quiz ordering options!";
+ if (! $options->id = $DB->insert_record('question_ordering', $options)) {
+ $result->error = 'Could not insert question ordering options!';
return $result;
}
}
- // delete old answer records
- if (!empty($oldanswers)) {
- foreach($oldanswers as $oa) {
- $DB->delete_records('question_answers', array('id' => $oa->id));
- }
+ // delete old answer records, if any
+ if (count($answerids)) {
+ $DB->delete_records_list('question_answers', 'id', $answerids);
}
- /// Perform sanity checks on fractional grades
return true;
}
public function get_question_options($question) {
global $DB, $OUTPUT;
- // Get additional information from database
- // and attach it to the question object
- if (!$question->options = $DB->get_record('question_ordering',
- array('question' => $question->id))) {
+
+ // load the options
+ if (! $question->options = $DB->get_record('question_ordering', array('question' => $question->id))) {
echo $OUTPUT->notification('Error: Missing question options!');
return false;
}
- // Load the answers
- if (!$question->options->answers = $DB->get_records('question_answers',
- array('question' => $question->id), 'id ASC')) {
- echo $OUTPUT->notification('Error: Missing question answers for truefalse question ' .
- $question->id . '!');
+
+ // Load the answers - "fraction" is used to signify the order of the answers
+ if (! $question->options->answers = $DB->get_records('question_answers', array('question' => $question->id), 'fraction ASC')) {
+ echo $OUTPUT->notification('Error: Missing question answers for ordering question ' . $question->id . '!');
return false;
}
+ //parent::get_question_options($question);
return true;
}
/*
@@ -195,10 +171,8 @@ class qtype_ordering extends question_type {
public function delete_question($questionid, $contextid) {
global $DB;
$DB->delete_records('question_ordering', array('question' => $questionid));
-
parent::delete_question($questionid, $contextid);
}
-
}
// NEW LINES START
diff --git a/question/type/ordering/renderer.php b/question/type/ordering/renderer.php
index b0fcce705a3..626ff51b472 100644
--- a/question/type/ordering/renderer.php
+++ b/question/type/ordering/renderer.php
@@ -34,121 +34,160 @@ defined('MOODLE_INTERNAL') || die();
class qtype_ordering_renderer extends qtype_renderer {
public function formulation_and_controls(question_attempt $qa, question_display_options $options) {
- global $DB, $CFG;
+ global $CFG, $DB;
+ static $addStyle = true;
+ static $addScript = true;
$question = $qa->get_question();
- if (! $ordering = $DB->get_record('question_ordering', array('question' => $question->id))) {
+ if (! $options = $DB->get_record('question_ordering', array('question' => $question->id))) {
return '';
}
- if (empty($ordering->studentsee)) {
- $ordering->studentsee = 100;
- } else {
- $ordering->studentsee += 2;
- }
- if (! $answers = $DB->get_records('question_answers', array('question' => $question->id), '', '*', 0, $ordering->studentsee)) {
+ if (! $answers = $DB->get_records('question_answers', array('question' => $question->id), '', '*')) {
return ''; // shouldn't happen !!
}
- shuffle($answers);
+
+ if ($options->studentsee==0) { // all items
+ $options->studentsee = count($answers);
+ } else {
+ // a nasty hack so that "studentsee" is the same
+ // as what is displayed by edit_ordering_form.php
+ $options->studentsee += 2;
+ }
+
+ switch ($options->logical) {
+
+ case 0: // all
+ $answerids = array_keys($answers);
+ break;
+
+ case 1: // random subset
+ $answerids = array_rand($answers, $options->studentsee);
+ break;
+
+ case 2: // contiguous subset
+ if (count($answers) > $options->studentsee) {
+ $offset = mt_rand(0, count($answers) - $options->studentsee);
+ $answers = array_slice($answers, $offset, $options->studentsee, true);
+ }
+ $answerids = array_keys($answers);
+ break;
+ }
+ shuffle($answerids);
$result = '';
- $result .= html_writer::tag('script', '', array('type'=>'text/javascript', 'src'=>$CFG->wwwroot.'/question/type/ordering/jquery.js'));
- $result .= html_writer::tag('script', '', array('type'=>'text/javascript', 'src'=>$CFG->wwwroot.'/question/type/ordering/jquery-ui.js'));
+ $result .= html_writer::tag('script', '', array('type'=>'text/javascript', 'src'=>$CFG->wwwroot.'/question/type/ordering/js/jquery.js'));
+ $result .= html_writer::tag('script', '', array('type'=>'text/javascript', 'src'=>$CFG->wwwroot.'/question/type/ordering/js/jquery-ui.js'));
$style = "\n";
- $style .= "ul.sortable li {\n";
+ $style .= "ul.sortable".$question->id." li {\n";
$style .= " position: relative;\n";
$style .= "}\n";
- $style .= "ul.boxy {\n";
- $style .= " border: 1px solid #ccc;\n";
- $style .= " float: left;\n";
- $style .= " font-family: Arial, sans-serif;\n";
- $style .= " font-size: 13px;\n";
- $style .= " list-style-type: none;\n";
- $style .= " margin: 0px;\n";
- $style .= " margin-left: 5px;\n";
- $style .= " padding: 4px 4px 0 4px;\n";
- $style .= " width: 360px;\n";
- $style .= "}\n";
- $style .= "ul.boxy li {\n";
- $style .= " background-color: #eeeeee;\n";
- $style .= " border: 1px solid #cccccc;\n";
- $style .= " border-image: initial;\n";
- $style .= " cursor: move;\n";
- $style .= " list-style-type: none;\n";
- $style .= " margin-bottom: 1px;\n";
- $style .= " min-height: 20px;\n";
- $style .= " padding: 8px 2px;\n";
- $style .= "}\n";
+ if ($addStyle) {
+ $addStyle = false; // only add style once
+ $style .= "ul.boxy {\n";
+ $style .= " border: 1px solid #ccc;\n";
+ $style .= " float: left;\n";
+ $style .= " font-family: Arial, sans-serif;\n";
+ $style .= " font-size: 13px;\n";
+ $style .= " list-style-type: none;\n";
+ $style .= " margin: 0px;\n";
+ $style .= " margin-left: 5px;\n";
+ $style .= " padding: 4px 4px 0 4px;\n";
+ $style .= " width: 360px;\n";
+ $style .= "}\n";
+ $style .= "ul.boxy li {\n";
+ $style .= " background-color: #eeeeee;\n";
+ $style .= " border: 1px solid #cccccc;\n";
+ $style .= " border-image: initial;\n";
+ $style .= " cursor: move;\n";
+ $style .= " list-style-type: none;\n";
+ $style .= " margin-bottom: 1px;\n";
+ $style .= " min-height: 20px;\n";
+ $style .= " padding: 8px 2px;\n";
+ $style .= "}\n";
+ }
$result .= html_writer::tag('style', $style, array('type' => 'text/css'));
$script = "\n";
+ $script .= "//id."').sortable({\n";
$script .= " update: function(event, ui) {\n";
$script .= " var ItemsOrder = $(this).sortable('toArray').toString();\n";
$script .= " $('#q".$question->id."').attr('value', ItemsOrder);\n";
$script .= " }\n";
$script .= " });\n";
- $script .= " $('#sortable').disableSelection();\n";
+ $script .= " $('#sortable".$question->id."').disableSelection();\n";
$script .= "});\n";
$script .= "$(document).ready(function() {\n";
- $script .= " var ItemsOrder = $('#sortable').sortable('toArray').toString();\n";
+ $script .= " var ItemsOrder = $('#sortable".$question->id."').sortable('toArray').toString();\n";
$script .= " $('#q".$question->id."').attr('value', ItemsOrder);\n";
$script .= "});\n";
+ $script .= "//]]>\n";
$result .= html_writer::tag('script', $script, array('type' => 'text/javascript'));
$result .= html_writer::tag('div', stripslashes($question->format_questiontext($qa)), array('class' => 'qtext'));
$result .= html_writer::start_tag('div', array('class' => 'ablock'));
$result .= html_writer::start_tag('div', array('class' => 'answer'));
- $result .= html_writer::start_tag('ul', array('class' => 'boxy', 'id' => 'sortable'));
+ $result .= html_writer::start_tag('ul', array('class' => 'boxy', 'id' => 'sortable'.$question->id));
- foreach ($answers as $answer) {
- // $answer->fraction holds the correct order - as a decimal ?!
- $id = 'ordering_item_'.$answer->id.'_'.intval($answer->fraction);
+ // generate ordering items
+ foreach ($answerids as $i => $answerid) {
+ // the original "id" revealed the correct order of the answers
+ // because $answer->fraction holds the correct order number
+ // $id = 'ordering_item_'.$answerid.'_'.intval($answers[$answerid]->fraction);
+ $id = 'ordering_item_'.md5($CFG->passwordsaltmain.$answers[$answerid]->answer);
$params = array('class' => 'ui-state-default', 'id' => $id);
- $result .= html_writer::tag('li', stripslashes($answer->answer), $params);
+ $result .= html_writer::tag('li', $answers[$answerid]->answer, $params);
}
$result .= html_writer::end_tag('ul');
$result .= html_writer::end_tag('div'); // answer
$result .= html_writer::end_tag('div'); // ablock
- $result .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'q'.$question->id, 'id' => 'q'.$question->id));
- $result .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'answer', 'value' => '712'));
+ $result .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'q'.$question->id, 'id' => 'q'.$question->id, 'value' => '9'));
+ $result .= html_writer::empty_tag('input', array('type'=>'hidden', 'name'=>'answer', 'value' => ''));
$result .= html_writer::tag('div', '', array('style' => 'clear:both;'));
$script = "\n";
- $script .= "function orderingTouchHandler(event) {\n";
- $script .= " var touch = event.changedTouches[0];\n";
- $script .= " switch (event.type) {\n";
- $script .= " case 'touchstart': var type = 'mousedown'; break;\n";
- $script .= " case 'touchmove': var type = 'mousemove'; event.preventDefault(); break;\n";
- $script .= " case 'touchend': var type = 'mouseup'; break;\n";
- $script .= " default: return;\n";
- $script .= " }\n";
- $script .= " var simulatedEvent = document.createEvent('MouseEvent');\n";
- $script .= " //initMouseEvent(type, canBubble, cancelable, view, clickCount, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);\n";
- $script .= " simulatedEvent.initMouseEvent(type, true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0/*left*/, null);\n";
- $script .= " touch.target.dispatchEvent(simulatedEvent);\n";
- $script .= " event.preventDefault();\n";
- $script .= "}\n";
- $script .= "function orderingInit() {\n";
- $script .= " var obj = document.getElementById('sortable');\n";
- $script .= " if (obj) {\n";
- $script .= " for (var i=0; iid."');\n";
+ $script .= "//]]>\n";
$result .= html_writer::tag('script', $script, array('type' => 'text/javascript'));
return $result;