MDL-47494 ddmarker: Merge pull request #7 from jamiepratt/wip_readme

Wip readme
This commit is contained in:
Tim Hunt
2012-06-20 02:46:47 -07:00
22 changed files with 958 additions and 60 deletions
+131
View File
@@ -0,0 +1,131 @@
Drag-and-drop markers question type
-----------------------------------
You can use markers with text labels as drag items onto rectangular, and in
Moodle 2.2+ version circular and polygon defined drop zones on a background image.
This question type requires that gapselect question type
https://github.com/moodleou/moodle-qtype_ddimageortext/ and
https://github.com/moodleou/moodle-qtype_gapselect/
to be installed in order to work.
This question type was written by Jamie Pratt (http://jamiep.org/).
This question type is compatible with Moodle 2.1+ (MOODLE_21_STABLE branch) or
2.2+ (master branch).
###Installation
####Installation Using Git
To install using git for a 2.2+ Moodle installation, type this command in the
root of your Moodle install:
git clone git://github.com/moodleou/moodle-qtype_ddmarker.git question/type/ddmarker
To install using git for a 2.1+ Moodle installation, type this command in the
root of your Moodle install:
git clone -b MOODLE_21_STABLE git://github.com/moodleou/moodle-qtype_ddmarker.git question/type/ddmarker
Then add question/type/ddmarker to your git ignore.
####Installation From Downloaded zip file
Alternatively, download the zip from :
* Moodle 2.2+ - https://github.com/moodleou/moodle-qtype_ddmarker/zipball/master
* Moodle 2.1+ - https://github.com/moodleou/moodle-qtype_ddmarker/zipball/MOODLE_21_STABLE
unzip it into the question/type folder, and then rename the new folder to ddmarker.
###Converting 'image target' type questions to this type
The imagetarget question type question type will not be upgraded to use with Moodle beyond version 1.9 it seems.
But you can convert your existing image target questions and question attempt data to be drag and drop marker questions and they
will work as the image target previously worked.
There are two ways to convert your imagetarget questions to ddmarker question types.
####Automatic Conversion (recommended)
Conversion will happen automatically when you upgrade for Moodle 2.0.
It is recommended you follow the following steps :
Upgrade your site to Moodle 2.0. This involves :
* Upgrade the code base to Moodle 2.0
* Remove the imagetarget question type code from question/type/imagetarget/
* Go to your http://{moodleroot}/admin/ to trigger the upgrade of the db
At this point your imagetarget questions won't work and will show up as 'missing type' but once that upgrade is
done change your Moodle code to Moodle 2.2+
* install the ddmarker question type code in question type ddmarker.
* then go to your http://{moodleroot}/admin/ to trigger the upgrade of the db
This will convert all your imagetarget questions to ddmarker automatically.
####Manual Conversion
You can also use a manual script to convert imagetarget questions to ddmarker after upgrading to Moodle 2.1 or greater.
* Log in as admin.
* You will find a script in the admin menu under plugins/question types/ to convert your imagetarget questions to ddmarker.
(This just converts your questions themselves.)
* In order to convert your question attempt data to be used with the ddmarker question type and Moodle 2.1 or greater you need to
find the 'question engine upgrade helper' which will appear at the root of the admin menu. Use this script to :
* _Reset the upgrade of all attempt data._
* _Run the attempt data upgrade again._
###Issues with converting image target question type questions
####Background image shrinkage
The ddmarker question type will shrink the background image of your questions to be within a maximum size and width while at the
time preserving aspect ratio of the image. The default max width is 600 pixels and height 400 pixels.
The ddmarker question type does this whenever you edit a question and save it again.
Unfortunately when you open up a question to edit it this means that if the image is to big it will be shrunk but at present the
position of your drop zones are not moved to compensate for this shrinkage. There won't be a problem until you try to edit and save
a question but when you open it in the editor the drop zones will not be in the correct position. If you save the question they
they will then be saved in the wrong position.
####Work around for background image shrinkage
Either :
* do not edit questions which have sizes above the allowed max.
* or you can change the allowed maximum size of images there are two constant at the top of question/type/ddmarker/questiontype.php
that define the size limits.
The limit is just there to shrink outrageously large images down to a reasonable size automatically. You could set the value of the
constants defining the max size to a very large value to effectively disable the image size constraints all together.
####Lack of drag label in imagetarget questions
Normally each draggable marker in the ddmarker question type has a text label. There are no labels for the imagetarget markers
though, I needed to pick something that will work in any language as the label for the single imagetarget draggable marker
so I picked 'X'.
####Work around for lack of drag label in imagetarget questions
Your teachers can edit this label after the question has been created. And they might also like to take advantage of the ability in
the ddmarker question type to be able to specify the correct drop zones for more than one drag marker onto the same image,
giving each drag marker a different label.
You can change the default drag marker label which you can find defined in a constant at the top of question/type/ddmarker/lib.php
####No automatic feedback telling the user whether they got the question right, partially right or wrong.
In the imagetarget question you get a text message telling the user whether they got the question correct, partially correct or
wrong. In many of the new question types in Moodle 2.1 onwards the teacher is expected to enter the message that the user will
see in the question definition. This is called 'combined feedback' and by default it is blank. So questions that have been
converted from per 2.1 Moodle, from imagetarget question types that used to give some feedback to the user will no longer do so.
####Work around for lack of automatic feedback telling the user whether they got the question right, partially right or wrong.
You can use this plug in https://github.com/jamiepratt/moodle-admin_tool_questionaddfeedback to bulk add feedback to questions.
-31
View File
@@ -1,31 +0,0 @@
Drag-and-drop markers question type
You can use markers with text labels as drag items onto rectangular, and in
Moodle 2.2+ version circular and polygon defined drop zones on a background image.
This question type requires that gapselect question type
https://github.com/moodleou/moodle-qtype_ddimageortext/ and
https://github.com/moodleou/moodle-qtype_gapselect/
to be installed in order to work.
This question type was written by Jamie Pratt (http://jamiep.org/).
This question type is compatible with Moodle 2.1+ (MOODLE_21_STABLE branch) or
2.2+ (master branch).
To install using git for a 2.2+ Moodle installation, type this command in the
root of your Moodle install:
git clone git://github.com/moodleou/moodle-qtype_ddmarker.git question/type/ddmarker
To install using git for a 2.1+ Moodle installation, type this command in the
root of your Moodle install:
git clone -b MOODLE_21_STABLE git://github.com/moodleou/moodle-qtype_ddmarker.git question/type/ddmarker
Then add question/type/ddmarker to your git ignore.
Alternatively, download the zip from
Moodle 2.2+ - https://github.com/moodleou/moodle-qtype_ddmarker/zipball/master
Moodle 2.1+ - https://github.com/moodleou/moodle-qtype_ddmarker/zipball/MOODLE_21_STABLE
unzip it into the question/type folder, and then rename the new folder to ddmarker.
@@ -15,9 +15,10 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package moodlecore
* @subpackage backup-moodle2
* @copyright 2011 The Open University
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
@@ -15,9 +15,10 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package moodlecore
* @subpackage backup-moodle2
* @copyright 2011 The Open University
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+79
View File
@@ -0,0 +1,79 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* ddmarker question type installation code.
*
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Installation code for the ddmarker question type. It converts all existing imagetarget questions to ddmarker
*/
function xmldb_qtype_ddmarker_install() {
global $DB, $OUTPUT;
$from = 'FROM {question_categories} cat, {question} q';
$where = ' WHERE q.qtype = \'imagetarget\' AND q.category = cat.id ';
$sql = 'SELECT q.*, cat.contextid '.$from.$where.'ORDER BY cat.id, q.name';
$questions = $DB->get_records_sql($sql);
if (!empty($questions)) {
require_once(dirname(__FILE__).'/../lib.php');
$dragssql = 'SELECT drag.* '.$from.', {qtype_ddmarker_drags} drag'.$where.' AND drag.questionid = q.id';
$drags = xmldb_qtype_ddmarker_index_array_of_records_by_key('questionid', $DB->get_records_sql($dragssql));
$dropssql = 'SELECT drp.* '.$from.', {qtype_ddmarker_drops} drp'.$where.' AND drp.questionid = q.id';
$drops = xmldb_qtype_ddmarker_index_array_of_records_by_key('questionid', $DB->get_records_sql($dropssql));
$answerssql = 'SELECT answer.* '.$from.', {question_answers} answer'.$where.' AND answer.question = q.id';
$answers = xmldb_qtype_ddmarker_index_array_of_records_by_key('question', $DB->get_records_sql($answerssql));
$imgfiles = $DB->get_records_sql_menu('SELECT question, qimage FROM {question_imagetarget}');
$progressbar = new progress_bar('qtype_ddmarker_convert_from_imagetarget');
$progressbar->create();
$done = 0;
foreach ($questions as $question) {
qtype_ddmarker_convert_image_target_question($question, $imgfiles[$question->id], $answers[$question->id]);
$done++;
$progressbar->update($done, count($questions), get_string('convertingimagetargetquestion', 'qtype_ddmarker', $question));
}
list($qsql, $qparams) = $DB->get_in_or_equal(array_keys($questions));
$DB->delete_records_select('question_answers', 'question '.$qsql, $qparams);
$dbman = $DB->get_manager();
$dbman->drop_table(new xmldb_table('question_imagetarget'));
}
}
function xmldb_qtype_ddmarker_index_array_of_records_by_key($key, $recs) {
$out = array();
foreach ($recs as $id => $rec) {
if (!isset($out[$rec->{$key}])) {
$out[$rec->{$key}] = array();
}
$out[$rec->{$key}][$id] = $rec;
}
return $out;
}
+85
View File
@@ -0,0 +1,85 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Upgrade library code for the ddmarker question type. This will only get triggered by the code
* to convert imagetarget questions to ddmarker.
*
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Class for converting attempt data from imagetarget questions when converting
* attempts to the new question engine.
*
* This class is used by the code in question/engine/upgrade/upgradelib.php.
*
* @copyright 2010 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_ddmarker_qe2_attempt_updater extends question_qtype_attempt_updater {
public function right_answer() {
$drag = reset($this->question->options->drags);
return '{'.get_string('dropzone', 'qtype_ddmarker', '1')." -> ".$drag->label.'}';
}
public function was_answered($state) {
return !empty($state->answer);
}
public function response_summary($state) {
if (!empty($state->answer)) {
$drag = reset($this->question->options->drags);
foreach ($this->question->options->drops as $drop) {
list($xy, $wh) = explode(';', $drop->coords);
list($x, $y) = explode(',', $xy);
list($w, $h) = explode(',', $wh);
list($answerx, $answery) = explode(',', $state->answer);
if (($answerx >= $x && $answerx <= ($x + $w)) && ($answery >= $y && $answery <= ($y + $h))) {
return '{'.get_string('dropzone', 'qtype_ddmarker', $drop->no)." -> ".$drag->label.'}';
}
}
return '';
} else {
return null;
}
}
public function question_summary() {
$drag = reset($this->question->options->drags);
return parent::question_summary().'[['.get_string('dropzone', 'qtype_ddmarker', '1')."]] -> {".$drag->label.'}';
}
public function set_first_step_data_elements($state, &$data) {
$data['_choiceorder1'] = '1';
}
public function supply_missing_first_step_data(&$data) {
}
public function set_data_elements_for_step($state, &$data) {
if (!empty($state->answer)) {
$data['c1'] = $state->answer;
}
}
}
@@ -24,7 +24,8 @@ define('QTYPE_DDMARKER_ALLOWED_TAGS_IN_MARKER', '<br><i><em><b><strong><sup><sub
*
* @package qtype
* @subpackage ddmarker
* @copyright 2009 The Open University
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -0,0 +1,158 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This page lets admin convert imagetarget questions to the ddmarker question type.
*
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(dirname(__FILE__) . '/../../../config.php');
require_once($CFG->libdir . '/adminlib.php');
require_once(dirname(__FILE__).'/questionlists.php');
require_once(dirname(__FILE__).'/lib.php');
class qtype_ddmarker_question_converter_list extends qtype_ddmarker_question_list {
protected function new_list_item($stringidentifier, $link, $record) {
return new qtype_ddmarker_question_converter_list_item($stringidentifier, $link, $record, $this, $this->categorylist);
}
public function prepare_for_processing($top) {
global $DB;
$questionids = $top->question_ids();
list($inorequalsql, $inorequalparams) = $DB->get_in_or_equal($questionids);
$imagetargetrecords = $DB->get_records_select('question_imagetarget', 'question '.$inorequalsql, $inorequalparams);
$answers = array();
foreach ($imagetargetrecords as $imagetargetrecord) {
$this->get_instance($imagetargetrecord->question)->imagetargetrecord = $imagetargetrecord;
}
$answerrecords = $DB->get_records_select('question_answers', 'question '.$inorequalsql, $inorequalparams);
foreach ($answerrecords as $answerrecord) {
$this->get_instance($answerrecord->question)->answers[] = $answerrecord;
}
}
}
class qtype_ddmarker_question_converter_list_item extends qtype_ddmarker_question_list_item {
public $imagetargetrecord = null;
public $answers = array();
public function process($renderer) {
qtype_ddmarker_convert_image_target_question($this->record, $this->imagetargetrecord->qimage, $this->answers);
parent::process($renderer);//outputs progress message
}
}
$categoryid = optional_param('categoryid', 0, PARAM_INT);
$qcontextid = optional_param('contextid', 0, PARAM_INT);
$questionid = optional_param('questionid', 0, PARAM_INT);
$confirm = optional_param('confirm', 0, PARAM_INT);
// Check the user is logged in.
require_login();
$context = get_context_instance(CONTEXT_SYSTEM);
require_capability('moodle/question:config', $context);
admin_externalpage_setup('qtypeddmarkerfromimagetarget');
// Header.
$renderer = $PAGE->get_renderer('qtype_ddmarker', 'list');
echo $renderer->header();
echo $renderer->heading(get_string('imagetargetconverter', 'qtype_ddmarker'), 2);
$params = array();
$from = 'FROM {question_categories} cat, {question} q';
$where = ' WHERE q.qtype = \'imagetarget\' AND q.category = cat.id ';
if ($qcontextid) {
$qcontext = get_context_instance_by_id($qcontextid, MUST_EXIST);
$from .= ', {context} context';
$where .= 'AND cat.contextid = context.id AND (context.path LIKE :path OR context.id = :id) ';
$params['path'] = $qcontext->path.'/%';
$params['id'] = $qcontext->id;
} else if ($categoryid) {
//fetch all questions from this cats context
$from .= ', {question_categories} cat2';
$where .= 'AND cat.contextid = cat2.contextid AND cat2.id = :categoryid ';
$params['categoryid'] = $categoryid;
} else if ($questionid) {
//fetch all questions from this cats context
$where .= 'AND q.id = :questionid ';
$params['questionid'] = $questionid;
}
$sql = 'SELECT q.*, cat.contextid '.$from.$where.'ORDER BY cat.id, q.name';
$questions = $DB->get_records_sql($sql, $params);
if (!count($questions)) {
echo html_writer::tag('div', get_string('noquestionsfound', 'qtype_ddmarker'));
} else {
$contextids = array();
foreach ($questions as $question) {
$contextids[] = $question->contextid;
}
$questionsselected = (bool) ($categoryid || $qcontextid || $questionid);
if (!$confirm) {
if (!$questionsselected) {
$pagestate = 'listall';
} else {
$pagestate = 'confirm';
}
} else if (confirm_sesskey()) {
$pagestate = 'processing';
}
$link = ($pagestate == 'listall');
$contextlist = new qtype_ddmarker_context_list($pagestate, $link, array_unique($contextids));
$categorylist = new qtype_ddmarker_category_list($pagestate, $link, $contextids, $contextlist);
$questionlist = new qtype_ddmarker_question_converter_list($pagestate, $link, $questions, $categorylist);
foreach ($questions as $question) {
$questionlist->leaf_node($question->id, 1);
}
if ($questionid) {
$top = $questionlist->get_instance($questionid);
} else if ($categoryid) {
$top = $categorylist->get_instance($categoryid);
} else if ($qcontextid) {
$top = $contextlist->get_instance($qcontextid);
} else {
$top = $contextlist->root_node();
}
switch ($pagestate) {
case 'listall' :
echo $renderer->render_qtype_ddmarker_list($top);
break;
case 'confirm' :
echo $renderer->render_qtype_ddmarker_list($top);
$cofirmedurl = new moodle_url($PAGE->url, compact('categoryid', 'contextid', 'questionid') + array('confirm'=>1));
$cancelurl = new moodle_url($PAGE->url);
echo $renderer->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl);
break;
case 'processing' :
$questionlist->prepare_for_processing($top);
echo '<ul>';
$top->process($renderer);
echo '</ul>';
break;
default :
break;
}
}
// Footer.
echo $renderer->footer();
@@ -18,7 +18,8 @@
*
* @package qtype
* @subpackage ddmarker
* @copyright 2011 The Open University
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -26,7 +27,9 @@ $string['addmoreitems'] = 'Blanks for {no} more markers';
$string['alttext'] = 'Alt text';
$string['answer'] = 'Answer';
$string['bgimage'] = 'Background image';
$string['confirmimagetargetconversion'] = 'You are about to convert the above image target questions to the drag and drop markers question type.';
$string['coords'] = 'Coords';
$string['convertingimagetargetquestion'] = 'Converted question "{$a->name}"';
$string['correctansweris'] = 'The correct answer is: {$a}';
$string['draggableimage'] = 'Draggable image';
$string['draggableitem'] = 'Draggable item';
@@ -48,11 +51,22 @@ $string['formerror_shapeoutsideboundsofbgimage'] = 'The shape you have defined g
$string['formerror_toomanysemicolons'] = 'There are too many semi colon separated parts to the coordinates you have specified. Your coordinates for a {$a->shape} should be expressed as - {$a->coordsstring}.';
$string['formerror_unrecognisedwidthheightpart'] = 'We do not recognise the width and height you have specified. Your coordinates for a {$a->shape} should be expressed as - {$a->coordsstring}.';
$string['formerror_unrecognisedxypart'] = 'We do not recognise the x,y coordinates you have specified. Your coordinates for a {$a->shape} should be expressed as - {$a->coordsstring}.';
$string['imagetargetconverter'] = 'Convert image target questions to drag and drop marker';
$string['infinite'] = 'Infinite';
$string['listitemconfirmcategory'] = 'About to convert all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)';
$string['listitemconfirmcontext'] = 'About to convert all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)';
$string['listitemconfirmquestion'] = 'About to convert question "{$a->name}"';
$string['listitemlistallcategory'] = 'Select all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)';
$string['listitemlistallcontext'] = 'Select all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)';
$string['listitemlistallquestion'] = 'Select question "{$a->name}"';
$string['listitemprocessingcategory'] = 'Converting all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)';
$string['listitemprocessingcontext'] = 'Converting all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)';
$string['listitemprocessingquestion'] = 'Converted question "{$a->name}"';
$string['marker'] = 'Marker';
$string['marker_n'] = 'Marker {no}';
$string['markers'] = 'Markers';
$string['nolabel'] = 'No label text';
$string['noquestionsfound'] = 'No questions found to convert here.';
$string['pleasedragatleastonemarker'] = 'Your answer is not complete, you must place at least one marker on the image.';
$string['pluginname'] = 'Drag and drop markers';
$string['pluginname_help'] = 'select a background image file, enter text labels for markers and define the drop zones on the background image to which they must be dragged.';
+106 -3
View File
@@ -17,16 +17,21 @@
/**
* Serve question type files
*
* @since 2.0
* @package qtype
* @subpackage essay
* @copyright Dongsheng Cai <[email protected]>
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
*
* @var string label to use for drag items when converting image target questions to ddmarker question type
*/
define('QTYPE_DDMARKER_LABEL_FOR_MARKER_FOR_IMAGE_TARGET_QS', 'X');
/**
* Checks file access for essay questions.
@@ -36,3 +41,101 @@ function qtype_ddmarker_pluginfile($course, $cm, $context, $filearea, $args, $fo
require_once($CFG->libdir . '/questionlib.php');
question_pluginfile($course, $context, 'qtype_ddmarker', $filearea, $args, $forcedownload, $options);
}
function qtype_ddmarker_course_context_id($catcontextid) {
$context = get_context_instance_by_id($catcontextid);
while ($context->contextlevel != CONTEXT_COURSE) {
$context = get_context_instance_by_id(get_parent_contextid($context));
}
return $context->id;
}
function qtype_ddmarker_convert_image_target_question($question, $imgfilename, $answers) {
global $DB, $OUTPUT;
$correctfeedback = '';
$correctfeedbackformat = 1;
$incorrectfeedback = '';
$incorrectfeedbackformat = 1;
$foundincorrectanswer = false;
foreach ($answers as $answer) {
$no = 1;
if ('*' !== $answer->answer) {
$drop = new stdClass();
$drop->questionid = $question->id;
$drop->shape = 'rectangle';
$drop->no = $no;
list($x1, $y1, $x2, $y2) = explode(',', $answer->answer);
$width = $x2 - $x1;
$height = $y2 - $y1;
$drop->coords = "{$x1},{$y1};{$width},{$height}";
$drop->choice = 1;
$DB->insert_record('qtype_ddmarker_drops', $drop);
$no++;
$correctfeedback = $answer->feedback;
$correctfeedbackformat = $answer->feedbackformat;
} else {
$foundincorrectanswer = true;
$incorrectfeedback = $answer->feedback;
$incorrectfeedbackformat = $answer->feedbackformat;
}
}
if (count($answers) < 2) {
echo $OUTPUT->notification('There are less than 2 answers. '.
'(Normally we expect at least a correct and incorrect answer). '.
'For question id '.$question->id.' "'.$question->name.'".',
'notifyproblem');
}
if (!$foundincorrectanswer) {
echo $OUTPUT->notification('No incorrect answer found for question id '.$question->id.' "'.$question->name.'".',
'notifyproblem');
}
$drag = new stdClass();
$drag->questionid = $question->id;
$drag->no = 1;
$drag->label = QTYPE_DDMARKER_LABEL_FOR_MARKER_FOR_IMAGE_TARGET_QS;
$drag->infinite = 0;
$DB->insert_record('qtype_ddmarker_drags', $drag);
$ddmarker = new stdClass();
$ddmarker->questionid = $question->id;
$ddmarker->shuffleanswers = 0;
$ddmarker->correctfeedback = $correctfeedback;
$ddmarker->correctfeedbackformat = $correctfeedbackformat;
$ddmarker->partiallycorrectfeedback = '';
$ddmarker->partiallycorrectfeedbackformat = 1;
$ddmarker->incorrectfeedback = $incorrectfeedback;
$ddmarker->incorrectfeedbackformat = $incorrectfeedbackformat;
$ddmarker->shownumcorrect = 0;
$ddmarker->showmisplaced = 0;
$DB->insert_record('qtype_ddmarker', $ddmarker);
$newrec = clone($question);
unset($newrec->contextid);
$newrec->qtype = 'ddmarker';
$newrec->timemodified = time();
$DB->update_record('question', $newrec);
$fs = get_file_storage();
//we need to look in the course legacy files area for file
$bgimagefile = $fs->get_file(qtype_ddmarker_course_context_id($question->contextid),
'course',
'legacy',
'0',
'/'.dirname($imgfilename).'/',
basename($imgfilename));
if ($bgimagefile === false) {
echo $OUTPUT->notification('File "'.$imgfilename.'" not found in legacy course files area. '.
'For question id '.$question->id.' "'.$question->name.'".',
'notifyproblem');
} else {
$newbgimagefile = new stdClass();
$newbgimagefile->component = 'qtype_ddmarker';
$newbgimagefile->filearea = 'bgimage';
$newbgimagefile->filepath = '/';
$newbgimagefile->itemid = $question->id;
$newbgimagefile->contextid = $question->contextid;
$fs->create_file_from_storedfile($newbgimagefile, $bgimagefile);
}
}
+4 -2
View File
@@ -17,8 +17,10 @@
/**
* Drag-and-drop markers question definition class.
*
* @package qtype_ddmarker
* @copyright 2009 The Open University
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+273
View File
@@ -0,0 +1,273 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
defined('MOODLE_INTERNAL') || die();
/**
* These classes handle transforming arrays of records into a linked tree of contexts, categories and questions.
*
* @package qtype
* @subpackage ddmarker
* @copyright 2012 Jamie Pratt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class qtype_ddmarker_list_item implements renderable {
/**
* @var count of questions contained in this item and sub items.
*/
protected $qcount = 0;
/**
* @var children array of pointers to list_items either category_list_items or context_list_items
*/
protected $children = array();
protected $stringidentifier;
protected $link;
protected $record;
protected $list;
protected $parentlist;
protected $listtype = null;
public function __construct($stringidentifier, $link, $record, $list, $parentlist = null) {
$this->stringidentifier = $stringidentifier;
$this->link = $link;
$this->record = $record;
$this->list = $list;
$this->parentlist = $parentlist;
}
public function add_child($child) {
$this->children[] = $child;
//array_unique relies on __toString() returning a unique string to determine if objects in array
//are the same or not
$this->children = array_unique($this->children);
}
abstract protected function parent_node ();
public function item_name() {
return $this->record->name;
}
public function id_param_name() {
return $this->listtype.'id';
}
public function get_id() {
return $this->record->id;
}
public function get_q_count() {
return $this->qcount;
}
public function get_string_identifier() {
return $this->stringidentifier;
}
public function get_linked() {
return $this->link;
}
public function get_list_type() {
return $this->listtype;
}
public function get_children() {
return $this->children;
}
public function leaf_to_root($qcount) {
$this->qcount += $qcount;
$parent = $this->parent_node();
if ($parent !== null) {
$parent->add_child($this);
$parent->leaf_to_root($qcount);
}
}
public function process($renderer) {
echo '<li>';
echo $renderer->item($this);
$this->process_children($renderer);
echo '</li>';
flush();
}
protected function process_children($renderer) {
echo '<ul>';
foreach ($this->children as $child) {
$child->process($renderer);
}
echo '</ul>';
}
public function question_ids() {
return $this->child_question_ids();
}
protected function child_question_ids() {
$ids = array();
foreach ($this->children as $child) {
$ids = array_merge($ids, $child->question_ids());
}
return $ids;
}
public function __toString() {
return get_class($this).' '.$this->record->id;
}
/**
* @return the course id in which this item is contained or the id of the front page course
*/
public function course_context_id() {
return $this->parent_node()->course_context_id();
}
}
class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item {
protected $listtype = 'category';
public function parent_node() {
if ($this->record->parent == 0) {
return $this->parentlist->get_instance($this->record->contextid);
} else {
return $this->list->get_instance($this->record->parent);
}
}
}
class qtype_ddmarker_question_list_item extends qtype_ddmarker_list_item {
protected $listtype = 'question';
public function parent_node() {
return $this->parentlist->get_instance($this->record->category);
}
public function question_ids() {
return array($this->record->id);
}
}
class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item {
protected $listtype = 'context';
public function parent_node() {
$pathids = explode('/', $this->record->path);
if (count($pathids) >= 3) {
return $this->list->get_instance($pathids[count($pathids)-2]);
} else {
return null;
}
}
public function item_name() {
return print_context_name($this->record);
}
public function course_context_id() {
if ((int)$this->record->contextlevel === CONTEXT_COURSE) {
return $this->record->id;
} else {
return parent::course_context_id();
}
}
}
/**
* Describes a nested list of listitems. This class and sub classes contain the functionality to build the nested list.
**/
abstract class qtype_ddmarker_list {
protected $records = array();
protected $instances = array();
abstract protected function new_list_item($stringidentifier, $link, $record);
protected function make_list_item_instances_from_records($stringidentifier, $link) {
if (!empty($this->records)) {
foreach ($this->records as $id => $record) {
$this->instances[$id] = $this->new_list_item($stringidentifier, $link, $record);
}
}
}
public function get_instance($id) {
return $this->instances[$id];
}
public function leaf_node ($id, $qcount) {
$instance = $this->get_instance($id);
$instance->leaf_to_root($qcount);
}
}
class qtype_ddmarker_context_list extends qtype_ddmarker_list {
protected function new_list_item($stringidentifier, $link, $record) {
return new qtype_ddmarker_context_list_item($stringidentifier, $link, $record, $this);
}
public function __construct($stringidentifier, $link, $contextids) {
global $DB;
$this->records = array();
foreach ($contextids as $contextid) {
if (!isset($this->records[$contextid])) {
$this->records[$contextid] = get_context_instance_by_id($contextid, MUST_EXIST);
}
$parents = get_parent_contexts($this->records[$contextid]);
foreach ($parents as $parentcontextid) {
if (!isset($this->records[$parentcontextid])) {
$this->records[$parentcontextid] =
get_context_instance_by_id($parentcontextid, MUST_EXIST);
}
}
}
$this->make_list_item_instances_from_records($stringidentifier, $link);
}
public function render($roottorender = null) {
if ($roottorender === null) {
$roottorender = $this->root_node();
}
$rootitem = html_writer::tag('li', $roottorender->render());
return html_writer::tag('ul', $rootitem);
}
public function root_node () {
return $this->get_instance(get_context_instance(CONTEXT_SYSTEM)->id);
}
}
class qtype_ddmarker_category_list extends qtype_ddmarker_list {
protected $contextlist;
protected function new_list_item($stringidentifier, $link, $record) {
return new qtype_ddmarker_category_list_item($stringidentifier, $link, $record, $this, $this->contextlist);
}
public function __construct($stringidentifier, $link, $contextids, $contextlist) {
global $DB;
$this->contextlist = $contextlist;
//probably most efficient way to reconstruct question category tree is to load all q cats in relevant contexts
list($sql, $params) = $DB->get_in_or_equal($contextids);
$this->records = $DB->get_records_select('question_categories', "contextid ".$sql, $params);
$this->make_list_item_instances_from_records($stringidentifier, $link);
}
}
class qtype_ddmarker_question_list extends qtype_ddmarker_list {
protected $categorylist;
protected function new_list_item($stringidentifier, $link, $record) {
return new qtype_ddmarker_question_list_item($stringidentifier, $link, $record, $this, $this->categorylist);
}
public function __construct($stringidentifier, $link, $questions, $categorylist) {
global $DB;
$this->categorylist = $categorylist;
$this->records = $questions;
$this->make_list_item_instances_from_records($stringidentifier, $link);
}
public function prepare_for_processing($top) {
}
}
+2 -1
View File
@@ -19,7 +19,8 @@
*
* @package qtype
* @subpackage ddmarker
* @copyright 2009 The Open University
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+37 -2
View File
@@ -17,14 +17,17 @@
/**
* Drag-and-drop markers question renderer class.
*
* @package qtype_ddmarker
* @copyright 2010 The Open University
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/question/type/rendererbase.php');
require_once($CFG->dirroot . '/question/type/ddimageortext/rendererbase.php');
@@ -156,4 +159,36 @@ class qtype_ddmarker_renderer extends qtype_ddtoimage_renderer_base {
$output .= parent::hint($qa, $hint);
return $output;
}
}
class qtype_ddmarker_list_renderer extends plugin_renderer_base {
public function render_qtype_ddmarker_list(qtype_ddmarker_list_item $top) {
$list = html_writer::tag('ul', html_writer::tag('li', $this->render_qtype_ddmarker_list_item($top)));
return $this->output->container($list, 'listofquestions');
}
public function render_qtype_ddmarker_list_item(qtype_ddmarker_list_item $listitem) {
return $this->item($listitem).$this->children($listitem);
}
public function item(qtype_ddmarker_list_item $item) {
global $PAGE;
$a = new stdClass();
$a->qcount = $item->get_q_count();
$a->name = $item->item_name();
$thisitem = get_string('listitem'.$item->get_string_identifier().$item->get_list_type(), 'qtype_ddmarker', $a);
if ($item->get_linked()) {
$actionurl = new moodle_url($PAGE->url, array($item->id_param_name() => $item->get_id()));
$thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl));
}
return $thisitem;
}
protected function children(qtype_ddmarker_list_item $item) {
$children = array();
foreach ($item->get_children() as $child) {
$children[] = $this->render_qtype_ddmarker_list_item($child);
}
return html_writer::alist($children);
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
*
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$settings = new admin_externalpage('qtypeddmarkerfromimagetarget',
get_string('imagetargetconverter', 'qtype_ddmarker'),
new moodle_url('/question/type/ddmarker/imagetargetconverter.php'),
'moodle/question:config');
+4 -2
View File
@@ -17,8 +17,10 @@
/**
* Drag-and-drop markers classes for dealing with shapes on the server side.
*
* @package qtype_ddmarker
* @copyright 2009 The Open University
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class qtype_ddmarker_shape {
+4 -2
View File
@@ -17,8 +17,10 @@
/**
* Test helpers for the drag-and-drop markers question type.
*
* @package qtype_ddmarker
* @copyright 2010 The Open University
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -17,8 +17,10 @@
/**
* Unit tests for the drag-and-drop markers question definition class.
*
* @package qtype_ddmarker
* @copyright 2010 The Open University
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -17,8 +17,10 @@
/**
* Unit tests for the drag-and-drop markers question definition class.
*
* @package qtype_ddmarker
* @copyright 2010 The Open University
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -19,7 +19,8 @@
*
* @package qtype
* @subpackage ddmarker
* @copyright 2010 The Open University
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -17,8 +17,10 @@
/**
* Unit tests for the drag-and-drop markers question type.
*
* @package qtype_ddmarker
* @copyright 2010 The Open University
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+4 -2
View File
@@ -17,8 +17,10 @@
/**
* Version information for the drag-and-drop markers question type.
*
* @package qtype_ddmarker
* @copyright 2011 The Open University
* @package qtype
* @subpackage ddmarker
* @copyright 2012 The Open University
* @author Jamie Pratt <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/