MDL-42105 questions: let attempts have a max fraction > 1.
authorTim Hunt <T.J.Hunt@open.ac.uk>
Wed, 2 Oct 2013 13:48:33 +0000 (14:48 +0100)
committerTim Hunt <T.J.Hunt@open.ac.uk>
Fri, 4 Oct 2013 16:52:19 +0000 (17:52 +0100)
This parallels question_attempt->minfraction, which allows the
fractional mark to go below zere.

This is needed to allow the certainty-base marking behaviours to work
better.

38 files changed:
admin/tool/qeupgradehelper/locallib.php
backup/moodle2/backup_stepslib.php
backup/moodle2/restore_stepslib.php
lang/en/question.php
lib/db/install.xml
lib/db/upgrade.php
question/behaviour/behaviourbase.php
question/behaviour/deferredcbm/behaviour.php
question/behaviour/immediatecbm/behaviour.php
question/behaviour/missing/behaviour.php
question/behaviour/missing/tests/missingbehaviour_test.php
question/behaviour/rendererbase.php
question/engine/datalib.php
question/engine/lib.php
question/engine/questionattempt.php
question/engine/questionattemptstep.php
question/engine/tests/helpers.php
question/engine/tests/questionattempt_db_test.php
question/engine/tests/questionattempt_with_steps_test.php
question/engine/tests/questionusagebyactivity_test.php
question/engine/tests/unitofwork_test.php
question/engine/upgrade/behaviourconverters.php
question/preview.php
question/type/calculated/tests/upgradelibnewqe_test.php
question/type/calculatedmulti/tests/upgradelibnewqe_test.php
question/type/calculatedsimple/tests/upgradelibnewqe_test.php
question/type/description/tests/upgradelibnewqe_test.php
question/type/essay/tests/upgradelibnewqe_test.php
question/type/match/tests/upgradelibnewqe_test.php
question/type/multianswer/question.php
question/type/multianswer/tests/upgradelibnewqe_test.php
question/type/multichoice/tests/upgradelibnewqe_test.php
question/type/numerical/tests/upgradelibnewqe_test.php
question/type/questionbase.php
question/type/random/tests/upgradelibnewqe_test.php
question/type/shortanswer/tests/upgradelibnewqe_test.php
question/type/truefalse/tests/upgradelibnewqe_test.php
version.php

index eda56a8..f471b23 100644 (file)
@@ -572,6 +572,7 @@ function tool_qeupgradehelper_generate_unit_test($questionsessionid, $namesuffix
             'variant' => 1,
             'maxmark' => {$question->maxmark},
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => '',
             'rightanswer' => '',
index 922318c..e7f6ea4 100644 (file)
@@ -209,7 +209,7 @@ abstract class backup_questions_activity_structure_step extends backup_activity_
 
         $qas = new backup_nested_element($nameprefix . 'question_attempts');
         $qa = new backup_nested_element($nameprefix . 'question_attempt', array('id'), array(
-                'slot', 'behaviour', 'questionid', 'maxmark', 'minfraction',
+                'slot', 'behaviour', 'questionid', 'maxmark', 'minfraction', 'maxfraction',
                 'flagged', 'questionsummary', 'rightanswer', 'responsesummary',
                 'timemodified'));
 
index 1afa523..dea8ab0 100644 (file)
@@ -4047,6 +4047,10 @@ abstract class restore_questions_activity_structure_step extends restore_activit
         $data->questionid      = $question->newitemid;
         $data->timemodified    = $this->apply_date_offset($data->timemodified);
 
+        if (!property_exists($data, 'maxfraction')) {
+            $data->maxfraction = 1;
+        }
+
         $newitemid = $DB->insert_record('question_attempts', $data);
 
         $this->set_mapping($nameprefix . 'question_attempt', $oldid, $newitemid);
index 50f6dc3..fa11934 100644 (file)
@@ -421,6 +421,7 @@ $string['submitted'] = 'Submit: {$a}';
 $string['technicalinfo'] = 'Technical information';
 $string['technicalinfo_help'] = 'This technical information is probably only useful for developers working on new question types. It may also be helpful when trying to diagnose problems with questions.';
 $string['technicalinfominfraction'] = 'Minimum fraction: {$a}';
+$string['technicalinfomaxfraction'] = 'Maximum fraction: {$a}';
 $string['technicalinfoquestionsummary'] = 'Question summary: {$a}';
 $string['technicalinforightsummary'] = 'Right answer summary: {$a}';
 $string['technicalinfostate'] = 'Question state: {$a}';
index f8f65cc..44e9adf 100644 (file)
         <FIELD NAME="variant" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="The variant of the qusetion being used."/>
         <FIELD NAME="maxmark" TYPE="number" LENGTH="12" NOTNULL="true" SEQUENCE="false" DECIMALS="7" COMMENT="The grade this question is marked out of in this attempt."/>
         <FIELD NAME="minfraction" TYPE="number" LENGTH="12" NOTNULL="true" SEQUENCE="false" DECIMALS="7" COMMENT="Some questions can award negative marks. This indicates the most negative mark that can be awarded, on the faction scale where the maximum positive mark is 1."/>
+        <FIELD NAME="maxfraction" TYPE="number" LENGTH="12" NOTNULL="true" DEFAULT="1" SEQUENCE="false" DECIMALS="7" COMMENT="Some questions can give fractions greater than 1. This indicates the greatest fraction that can be awarded."/>
         <FIELD NAME="flagged" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether this question has been flagged within the attempt."/>
         <FIELD NAME="questionsummary" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="If this question uses randomisation, it should set this field to summarise what random version the student actually saw. This is a human-readable textual summary of the student's response which might, for example, be used in a report."/>
         <FIELD NAME="rightanswer" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="This is a human-readable textual summary of the right answer to this question. Might be used, for example on the quiz preview, to help people who are testing the question. Or might be used in reports."/>
index 5409977..968f04e 100644 (file)
@@ -2576,5 +2576,20 @@ function xmldb_main_upgrade($oldversion) {
         upgrade_main_savepoint(true, 2013092700.01);
     }
 
+    if ($oldversion < 2013100400.01) {
+
+        // Define field maxfraction to be added to question_attempts.
+        $table = new xmldb_table('question_attempts');
+        $field = new xmldb_field('maxfraction', XMLDB_TYPE_NUMBER, '12, 7', null, XMLDB_NOTNULL, null, '1', 'minfraction');
+
+        // Conditionally launch add field maxfraction.
+        if (!$dbman->field_exists($table, $field)) {
+            $dbman->add_field($table, $field);
+        }
+
+        // Main savepoint reached.
+        upgrade_main_savepoint(true, 2013100400.01);
+    }
+
     return true;
 }
index 06a12e9..97bcde8 100644 (file)
@@ -160,15 +160,27 @@ abstract class question_behaviour {
     /**
      * What is the minimum fraction that can be scored for this question.
      * Normally this will be based on $this->question->get_min_fraction(),
-     * but may be modified in some way by the model.
+     * but may be modified in some way by the behaviour.
      *
      * @return number the minimum fraction when this question is attempted under
-     * this model.
+     * this behaviour.
      */
     public function get_min_fraction() {
         return 0;
     }
 
+    /**
+     * Return the maximum possible fraction that can be scored for this question.
+     * Normally this will be based on $this->question->get_max_fraction(),
+     * but may be modified in some way by the behaviour.
+     *
+     * @return number the maximum fraction when this question is attempted under
+     * this behaviour.
+     */
+    public function get_max_fraction() {
+        return $this->question->get_max_fraction();
+    }
+
     /**
      * Return an array of the behaviour variables that could be submitted
      * as part of a question of this type, with their types, so they can be
@@ -432,7 +444,7 @@ abstract class question_behaviour {
                             $pendingstep->get_behaviour_var('maxmark');
             if ($pendingstep->get_behaviour_var('mark') === '') {
                 $fraction = null;
-            } else if ($fraction > 1 || $fraction < $this->qa->get_min_fraction()) {
+            } else if ($fraction > $this->qa->get_max_fraction() || $fraction < $this->qa->get_min_fraction()) {
                 throw new coding_exception('Score out of range when processing ' .
                         'a manual grading action.', 'Question ' . $this->question->id .
                                 ', slot ' . $this->qa->get_slot() . ', fraction ' . $fraction);
index 4300119..af487ea 100644 (file)
@@ -49,6 +49,10 @@ class qbehaviour_deferredcbm extends qbehaviour_deferredfeedback {
         return question_cbm::adjust_fraction(parent::get_min_fraction(), question_cbm::HIGH);
     }
 
+    public function get_max_fraction() {
+        return question_cbm::adjust_fraction(parent::get_max_fraction(), question_cbm::HIGH);
+    }
+
     public function get_expected_data() {
         if ($this->qa->get_state()->is_active()) {
             return array('certainty' => PARAM_INT);
index ed81c24..add1388 100644 (file)
@@ -47,6 +47,10 @@ class qbehaviour_immediatecbm extends qbehaviour_immediatefeedback {
         return question_cbm::adjust_fraction(parent::get_min_fraction(), question_cbm::HIGH);
     }
 
+    public function get_max_fraction() {
+        return question_cbm::adjust_fraction(parent::get_max_fraction(), question_cbm::HIGH);
+    }
+
     public function get_expected_data() {
         if ($this->qa->get_state()->is_active()) {
             return array(
index 35bbea4..0c3e31f 100644 (file)
@@ -68,4 +68,9 @@ class qbehaviour_missing extends question_behaviour {
         throw new coding_exception('The behaviour used for this question is not available. ' .
                 'No processing is possible.');
     }
+
+    public function get_max_fraction() {
+        throw new coding_exception('The behaviour used for this question is not available. ' .
+                'No processing is possible.');
+    }
 }
index 4922ae7..7c02042 100644 (file)
@@ -53,25 +53,32 @@ class qbehaviour_missing_test extends advanced_testcase {
         $behaviour->process_action(new question_attempt_pending_step(array()));
     }
 
-    public function test_missing_cannot_get_min_grade() {
+    public function test_missing_cannot_get_min_fraction() {
         $qa = new question_attempt(test_question_maker::make_question('truefalse', 'true'), 0);
         $behaviour = new qbehaviour_missing($qa, 'deferredfeedback');
         $this->setExpectedException('moodle_exception');
         $behaviour->get_min_fraction();
     }
 
+    public function test_missing_cannot_get_max_fraction() {
+        $qa = new question_attempt(test_question_maker::make_question('truefalse', 'true'), 0);
+        $behaviour = new qbehaviour_missing($qa, 'deferredfeedback');
+        $this->setExpectedException('moodle_exception');
+        $behaviour->get_max_fraction();
+    }
+
     public function test_render_missing() {
         $records = new question_test_recordset(array(
             array('questionattemptid', 'contextid', 'questionusageid', 'slot',
-                                   'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
+                                   'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction', 'flagged',
                                             'questionsummary', 'rightanswer', 'responsesummary',
                     'timemodified', 'attemptstepid', 'sequencenumber', 'state', 'fraction',
                                                        'timecreated', 'userid', 'name', 'value'),
-            array(1, 123, 1, 1, 'strangeunknown', -1, 1, 2.0000000, 0.0000000, 0, '', '', '',
+            array(1, 123, 1, 1, 'strangeunknown', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '',
                     1256233790, 1, 0, 'todo',     null, 1256233700, 1,   '_order', '1,2,3'),
-            array(1, 123, 1, 1, 'strangeunknown', -1, 1, 2.0000000, 0.0000000, 0, '', '', '',
+            array(1, 123, 1, 1, 'strangeunknown', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '',
                     1256233790, 2, 1, 'complete', 0.50, 1256233705, 1,  '-submit',  '1'),
-            array(1, 123, 1, 1, 'strangeunknown', -1, 1, 2.0000000, 0.0000000, 0, '', '', '',
+            array(1, 123, 1, 1, 'strangeunknown', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '',
                     1256233790, 2, 1, 'complete', 0.50, 1256233705, 1,  'choice0',  '1'),
         ));
 
index 6a24e38..932ee30 100644 (file)
@@ -140,11 +140,15 @@ abstract class qbehaviour_renderer extends plugin_renderer_base {
                 'type' => 'hidden',
                 'name' => $qa->get_control_field_name('minfraction'),
                 'value' => $qa->get_min_fraction(),
+            )) . html_writer::empty_tag('input', array(
+                'type' => 'hidden',
+                'name' => $qa->get_control_field_name('maxfraction'),
+                'value' => $qa->get_max_fraction(),
             ));
 
             $errorclass = '';
             $error = '';
-            if ($currentmark > $maxmark || $currentmark < $maxmark * $qa->get_min_fraction()) {
+            if ($currentmark > $maxmark * $qa->get_max_fraction() || $currentmark < $maxmark * $qa->get_min_fraction()) {
                 $errorclass = ' error';
                 $error = html_writer::tag('span', get_string('manualgradeoutofrange', 'question'),
                         array('class' => 'error')) . html_writer::empty_tag('br');
index 68e3bc4..41d1ce1 100644 (file)
@@ -106,6 +106,7 @@ class question_engine_data_mapper {
         $record->variant = $qa->get_variant();
         $record->maxmark = $qa->get_max_mark();
         $record->minfraction = $qa->get_min_fraction();
+        $record->maxfraction = $qa->get_max_fraction();
         $record->flagged = $qa->is_flagged();
         $record->questionsummary = $qa->get_question_summary();
         if (core_text::strlen($record->questionsummary) > question_bank::MAX_SUMMARY_LENGTH) {
@@ -259,6 +260,7 @@ SELECT
     qa.variant,
     qa.maxmark,
     qa.minfraction,
+    qa.maxfraction,
     qa.flagged,
     qa.questionsummary,
     qa.rightanswer,
@@ -318,6 +320,7 @@ SELECT
     qa.variant,
     qa.maxmark,
     qa.minfraction,
+    qa.maxfraction,
     qa.flagged,
     qa.questionsummary,
     qa.rightanswer,
@@ -377,6 +380,7 @@ ORDER BY
     qa.variant,
     qa.maxmark,
     qa.minfraction,
+    qa.maxfraction,
     qa.flagged,
     qa.questionsummary,
     qa.rightanswer,
@@ -641,6 +645,7 @@ SELECT
     qa.variant,
     qa.maxmark,
     qa.minfraction,
+    qa.maxfraction,
     qa.flagged,
     qa.questionsummary,
     qa.rightanswer,
@@ -708,6 +713,7 @@ ORDER BY
         $record->id = $qa->get_database_id();
         $record->maxmark = $qa->get_max_mark();
         $record->minfraction = $qa->get_min_fraction();
+        $record->maxfraction = $qa->get_max_fraction();
         $record->flagged = $qa->is_flagged();
         $record->questionsummary = $qa->get_question_summary();
         $record->rightanswer = $qa->get_right_answer_summary();
@@ -949,6 +955,7 @@ ORDER BY
                        {$alias}qa.variant,
                        {$alias}qa.maxmark,
                        {$alias}qa.minfraction,
+                       {$alias}qa.maxfraction,
                        {$alias}qa.flagged,
                        {$alias}qa.questionsummary,
                        {$alias}qa.rightanswer,
index 4ba9eb3..9a6ad90 100644 (file)
@@ -142,7 +142,8 @@ abstract class question_engine {
         $mark = question_utils::optional_param_mark($prefix . '-mark');
         $maxmark = optional_param($prefix . '-maxmark', null, PARAM_FLOAT);
         $minfraction = optional_param($prefix . ':minfraction', null, PARAM_FLOAT);
-        return is_null($mark) || ($mark >= $minfraction * $maxmark && $mark <= $maxmark);
+        $maxfraction = optional_param($prefix . ':maxfraction', null, PARAM_FLOAT);
+        return is_null($mark) || ($mark >= $minfraction * $maxmark && $mark <= $maxfraction * $maxmark);
     }
 
     /**
index 1f36349..3c3acff 100644 (file)
@@ -87,15 +87,25 @@ class question_attempt {
     /** @var int which variant of the question to use. */
     protected $variant;
 
-    /** @var number the maximum mark that can be scored at this question. */
+    /**
+     * @var float the maximum mark that can be scored at this question.
+     * Actually, this is only really a nominal maximum. It might be better thought
+     * of as the question weight.
+     */
     protected $maxmark;
 
     /**
-     * @var number the minimum fraction that can be scored at this question, so
+     * @var float the minimum fraction that can be scored at this question, so
      * the minimum mark is $this->minfraction * $this->maxmark.
      */
     protected $minfraction = null;
 
+    /**
+     * @var float the maximum fraction that can be scored at this question, so
+     * the maximum mark is $this->maxfraction * $this->maxmark.
+     */
+    protected $maxfraction = null;
+
     /**
      * @var string plain text summary of the variant of the question the
      * student saw. Intended for reporting purposes.
@@ -649,19 +659,32 @@ class question_attempt {
         return $fraction * $this->maxmark;
     }
 
-    /** @return number the maximum mark possible for this question attempt. */
+    /**
+     * @return float the maximum mark possible for this question attempt.
+     * In fact, this is not strictly the maximum, becuase get_max_fraction may
+     * return a number greater than 1. It might be better to think of this as a
+     * question weight.
+     */
     public function get_max_mark() {
         return $this->maxmark;
     }
 
-    /** @return number the maximum mark possible for this question attempt. */
+    /** @return float the maximum mark possible for this question attempt. */
     public function get_min_fraction() {
         if (is_null($this->minfraction)) {
-            throw new coding_exception('This question_attempt has not been started yet, the min fraction is not yet konwn.');
+            throw new coding_exception('This question_attempt has not been started yet, the min fraction is not yet known.');
         }
         return $this->minfraction;
     }
 
+    /** @return float the maximum mark possible for this question attempt. */
+    public function get_max_fraction() {
+        if (is_null($this->maxfraction)) {
+            throw new coding_exception('This question_attempt has not been started yet, the max fraction is not yet known.');
+        }
+        return $this->maxfraction;
+    }
+
     /**
      * The current mark, formatted to the stated number of decimal places. Uses
      * {@link format_float()} to format floats according to the current locale.
@@ -885,8 +908,9 @@ class question_attempt {
             $this->behaviour = new $class($this, $preferredbehaviour);
         }
 
-        // Record the minimum fraction.
+        // Record the minimum and maximum fractions.
         $this->minfraction = $this->behaviour->get_min_fraction();
+        $this->maxfraction = $this->behaviour->get_max_fraction();
 
         // Initialise the first step.
         $firststep = new question_attempt_step($submitteddata, $timestamp, $userid, $existingstepid);
@@ -1287,6 +1311,7 @@ class question_attempt {
         $qa->set_slot($record->slot);
         $qa->variant = $record->variant + 0;
         $qa->minfraction = $record->minfraction + 0;
+        $qa->maxfraction = $record->maxfraction + 0;
         $qa->set_flagged($record->flagged);
         $qa->questionsummary = $record->questionsummary;
         $qa->rightanswer = $record->rightanswer;
@@ -1389,6 +1414,7 @@ class question_attempt_with_restricted_history extends question_attempt {
         $this->question = $this->baseqa->question;
         $this->maxmark = $this->baseqa->maxmark;
         $this->minfraction = $this->baseqa->minfraction;
+        $this->maxfraction = $this->baseqa->maxfraction;
         $this->questionsummary = $this->baseqa->questionsummary;
         $this->responsesummary = $this->baseqa->responsesummary;
         $this->rightanswer = $this->baseqa->rightanswer;
index 892c738..d2174e2 100644 (file)
@@ -32,7 +32,7 @@ defined('MOODLE_INTERNAL') || die();
  *
  * The most important attributes of a step are the state, which is one of the
  * {@link question_state} constants, the fraction, which may be null, or a
- * number bewteen the attempt's minfraction and 1.0, and the array of submitted
+ * number bewteen the attempt's minfraction and maxfraction, and the array of submitted
  * data, about which more later.
  *
  * A step also tracks the time it was created, and the user responsible for
@@ -76,7 +76,10 @@ class question_attempt_step {
      */
     private $state;
 
-    /** @var null|number the fraction (grade on a scale of minfraction .. 1.0) or null. */
+    /**
+     * @var null|number the fraction (grade on a scale of
+     * minfraction .. maxfraction, normally 0..1) or null.
+     */
     private $fraction = null;
 
     /** @var integer the timestamp when this step was created. */
@@ -148,7 +151,8 @@ class question_attempt_step {
     }
 
     /**
-     * @return null|number the fraction (grade on a scale of minfraction .. 1.0)
+     * @return null|number the fraction (grade on a scale of
+     * minfraction .. maxfraction, normally 0..1),
      * or null if this step has not been marked.
      */
     public function get_fraction() {
index 5542014..a02cd0c 100644 (file)
@@ -43,6 +43,9 @@ class testable_question_attempt extends question_attempt {
     public function set_min_fraction($fraction) {
         $this->minfraction = $fraction;
     }
+    public function set_max_fraction($fraction) {
+        $this->maxfraction = $fraction;
+    }
     public function set_behaviour(question_behaviour $behaviour) {
         $this->behaviour = $behaviour;
     }
index 1f9f970..bef8788 100644 (file)
@@ -44,18 +44,18 @@ class question_attempt_db_test extends data_loading_method_test_base {
     public function test_load() {
         $records = new question_test_recordset(array(
             array('questionattemptid', 'contextid', 'questionusageid', 'slot',
-                                   'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
+                                   'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction', 'flagged',
                                                                                        'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
                                                                                                                'attemptstepid', 'sequencenumber', 'state', 'fraction',
                                                                                                                                                 'timecreated', 'userid', 'name', 'value'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo',              null, 1256233700, 1,       null, null),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 2, 1, 'complete',          null, 1256233705, 1,   'answer',  '1'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1, '', '', '', 1256233790, 3, 2, 'complete',          null, 1256233710, 1,   'answer',  '0'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 4, 3, 'complete',          null, 1256233715, 1,   'answer',  '1'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 5, 4, 'gradedright',  1.0000000, 1256233720, 1,  '-finish',  '1'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1, '-comment', 'Not good enough!'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1,    '-mark',  '1'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1, '-maxmark',  '2'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo',              null, 1256233700, 1,       null, null),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 2, 1, 'complete',          null, 1256233705, 1,   'answer',  '1'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 1, '', '', '', 1256233790, 3, 2, 'complete',          null, 1256233710, 1,   'answer',  '0'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 4, 3, 'complete',          null, 1256233715, 1,   'answer',  '1'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 5, 4, 'gradedright',  1.0000000, 1256233720, 1,  '-finish',  '1'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1, '-comment', 'Not good enough!'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1,    '-mark',  '1'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 6, 5, 'mangrpartial', 0.5000000, 1256233790, 1, '-maxmark',  '2'),
         ));
 
         $question = test_question_maker::make_question('truefalse', 'true');
@@ -117,11 +117,11 @@ class question_attempt_db_test extends data_loading_method_test_base {
     public function test_load_missing_question() {
         $records = new question_test_recordset(array(
             array('questionattemptid', 'contextid', 'questionusageid', 'slot',
-                                   'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
+                                   'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction', 'flagged',
                                                                                        'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
                                                                                                                'attemptstepid', 'sequencenumber', 'state', 'fraction',
                                                                                                                                                 'timecreated', 'userid', 'name', 'value'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo',              null, 1256233700, 1,       null, null),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo',              null, 1256233700, 1,       null, null),
         ));
 
         question_bank::start_unit_test();
@@ -144,14 +144,14 @@ class question_attempt_db_test extends data_loading_method_test_base {
     public function test_load_with_autosaved_data() {
         $records = new question_test_recordset(array(
             array('questionattemptid', 'contextid', 'questionusageid', 'slot',
-                                   'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
+                                   'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction', 'flagged',
                                                                                        'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
                                                                                                              'attemptstepid', 'sequencenumber', 'state', 'fraction',
                                                                                                                                                 'timecreated', 'userid', 'name', 'value'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 4, -3, 'complete',          null, 1256233715, 1,   'answer',  '1'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 1,  0, 'todo',              null, 1256233700, 1,       null, null),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 2,  1, 'complete',          null, 1256233705, 1,   'answer',  '1'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1, '', '', '', 1256233790, 3,  2, 'complete',          null, 1256233710, 1,   'answer',  '0'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 4, -3, 'complete',          null, 1256233715, 1,   'answer',  '1'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 1,  0, 'todo',              null, 1256233700, 1,       null, null),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 2,  1, 'complete',          null, 1256233705, 1,   'answer',  '1'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 1, '', '', '', 1256233790, 3,  2, 'complete',          null, 1256233710, 1,   'answer',  '0'),
         ));
 
         $question = test_question_maker::make_question('truefalse', 'true');
@@ -203,15 +203,15 @@ class question_attempt_db_test extends data_loading_method_test_base {
         // There is also a second lot of redundant data to delete.
         $records = new question_test_recordset(array(
             array('questionattemptid', 'contextid', 'questionusageid', 'slot',
-                                   'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
+                                   'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction', 'flagged',
                                                                                        'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
                                                                                                              'attemptstepid', 'sequencenumber', 'state', 'fraction',
                                                                                                                                                 'timecreated', 'userid', 'name', 'value'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 5, -2, 'complete',          null, 1256233715, 1,   'answer',  '0'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 4, -1, 'complete',          null, 1256233715, 1,   'answer',  '0'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 1,  0, 'todo',              null, 1256233700, 1,       null, null),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 2,  1, 'complete',          null, 1256233705, 1,   'answer',  '1'),
-            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1, '', '', '', 1256233790, 3,  2, 'complete',          null, 1256233710, 1,   'answer',  '0'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 5, -2, 'complete',          null, 1256233715, 1,   'answer',  '0'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 4, -1, 'complete',          null, 1256233715, 1,   'answer',  '0'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 1,  0, 'todo',              null, 1256233700, 1,       null, null),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 2,  1, 'complete',          null, 1256233705, 1,   'answer',  '1'),
+            array(1, 123, 1, 1, 'deferredfeedback', -1, 1, 2.0000000, 0.0000000, 1.0000000, 1, '', '', '', 1256233790, 3,  2, 'complete',          null, 1256233710, 1,   'answer',  '0'),
         ));
 
         $question = test_question_maker::make_question('truefalse', 'true');
index 72553fa..b5f1d4b 100644 (file)
@@ -146,7 +146,7 @@ class question_attempt_with_steps_test extends advanced_testcase {
 
     public function test_get_min_fraction() {
         $this->qa->set_min_fraction(-1);
-        $this->assertEquals(-1, $this->qa->get_min_fraction(0));
+        $this->assertEquals(-1, $this->qa->get_min_fraction());
     }
 
     public function test_cannot_get_min_fraction_before_start() {
@@ -154,4 +154,15 @@ class question_attempt_with_steps_test extends advanced_testcase {
         $this->setExpectedException('moodle_exception');
         $qa->get_min_fraction();
     }
+
+    public function test_get_max_fraction() {
+        $this->qa->set_max_fraction(2);
+        $this->assertEquals(2, $this->qa->get_max_fraction());
+    }
+
+    public function test_cannot_get_max_fraction_before_start() {
+        $qa = new question_attempt($this->question, 0);
+        $this->setExpectedException('moodle_exception');
+        $qa->get_max_fraction();
+    }
 }
index 4caef12..a268c86 100644 (file)
@@ -173,13 +173,13 @@ class question_usage_db_test extends data_loading_method_test_base {
         $records = new question_test_recordset(array(
         array('qubaid', 'contextid', 'component', 'preferredbehaviour',
                                                'questionattemptid', 'questionusageid', 'slot',
-                                                              'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
+                                                              'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction', 'flagged',
                                                                                                              'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
                                                                                                                                      'attemptstepid', 'sequencenumber', 'state', 'fraction',
                                                                                                                                                                      'timecreated', 'userid', 'name', 'value'),
-        array(1, $scid, 'unit_test', 'interactive', 1, 1, 1, 'interactive', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo',             null, 1256233700, 1,       null, null),
-        array(1, $scid, 'unit_test', 'interactive', 1, 1, 1, 'interactive', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 2, 1, 'todo',             null, 1256233705, 1,   'answer',  '1'),
-        array(1, $scid, 'unit_test', 'interactive', 1, 1, 1, 'interactive', -1, 1, 2.0000000, 0.0000000, 0, '', '', '', 1256233790, 5, 2, 'gradedright', 1.0000000, 1256233720, 1,  '-finish',  '1'),
+        array(1, $scid, 'unit_test', 'interactive', 1, 1, 1, 'interactive', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo',             null, 1256233700, 1,       null, null),
+        array(1, $scid, 'unit_test', 'interactive', 1, 1, 1, 'interactive', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 2, 1, 'todo',             null, 1256233705, 1,   'answer',  '1'),
+        array(1, $scid, 'unit_test', 'interactive', 1, 1, 1, 'interactive', -1, 1, 2.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 5, 2, 'gradedright', 1.0000000, 1256233720, 1,  '-finish',  '1'),
         ));
 
         $question = test_question_maker::make_question('truefalse', 'true');
@@ -231,13 +231,13 @@ class question_usage_db_test extends data_loading_method_test_base {
         $records = new question_test_recordset(array(
         array('qubaid', 'contextid', 'component', 'preferredbehaviour',
                                                    'questionattemptid', 'questionusageid', 'slot',
-                                                             'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
+                                                             'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction', 'flagged',
                                                                                                             'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
                                                                                                                                                                                'attemptstepid', 'sequencenumber', 'state', 'fraction',
                                                                                                                                                                                                          'timecreated', 'userid', 'name', 'value'),
-        array(1, $scid, 'unit_test', 'interactive', 1, 1, 1, 'interactive', 0, 1, 1.0000000, 0.0000000, 0, 'This question is missing. Unable to display anything.', '', '', 0, null, null, null, null, null, null, null, null),
-        array(1, $scid, 'unit_test', 'interactive', 2, 1, 2, 'interactive', 0, 1, 1.0000000, 0.0000000, 0, 'This question is missing. Unable to display anything.', '', '', 0, null, null, null, null, null, null, null, null),
-        array(1, $scid, 'unit_test', 'interactive', 3, 1, 3, 'interactive', 0, 1, 1.0000000, 0.0000000, 0, 'This question is missing. Unable to display anything.', '', '', 0, null, null, null, null, null, null, null, null),
+        array(1, $scid, 'unit_test', 'interactive', 1, 1, 1, 'interactive', 0, 1, 1.0000000, 0.0000000, 1.0000000, 0, 'This question is missing. Unable to display anything.', '', '', 0, null, null, null, null, null, null, null, null),
+        array(1, $scid, 'unit_test', 'interactive', 2, 1, 2, 'interactive', 0, 1, 1.0000000, 0.0000000, 1.0000000, 0, 'This question is missing. Unable to display anything.', '', '', 0, null, null, null, null, null, null, null, null),
+        array(1, $scid, 'unit_test', 'interactive', 3, 1, 3, 'interactive', 0, 1, 1.0000000, 0.0000000, 1.0000000, 0, 'This question is missing. Unable to display anything.', '', '', 0, null, null, null, null, null, null, null, null),
         ));
 
         question_bank::start_unit_test();
@@ -263,11 +263,11 @@ class question_usage_db_test extends data_loading_method_test_base {
         $records = new question_test_recordset(array(
         array('qubaid', 'contextid', 'component', 'preferredbehaviour',
                                                    'questionattemptid', 'questionusageid', 'slot',
-                                                                        'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
+                                                                        'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction', 'flagged',
                                                                                                                'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
                                                                                                                                          'attemptstepid', 'sequencenumber', 'state', 'fraction',
                                                                                                                                                                    'timecreated', 'userid', 'name', 'value'),
-        array(1, $scid, 'unit_test', 'interactive', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null),
+        array(1, $scid, 'unit_test', 'interactive', null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null),
         ));
 
         question_bank::start_unit_test();
index 0b0b8b5..17cec0d 100644 (file)
@@ -82,17 +82,17 @@ class question_engine_unit_of_work_test extends data_loading_method_test_base {
         return array(
         array('qubaid', 'contextid', 'component', 'preferredbehaviour',
                                                 'questionattemptid', 'contextid', 'questionusageid', 'slot',
-                                                               'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'flagged',
+                                                               'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction', 'flagged',
                                                                                                               'questionsummary', 'rightanswer', 'responsesummary', 'timemodified',
                                                                                                                                      'attemptstepid', 'sequencenumber', 'state', 'fraction',
                                                                                                                                                                      'timecreated', 'userid', 'name', 'value'),
-        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo',             null, 1256233700, 1, '-_triesleft', 3),
-        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 0, '', '', '', 1256233790, 2, 1, 'todo',             null, 1256233720, 1, 'answer',     'toad'),
-        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 0, '', '', '', 1256233790, 2, 1, 'todo',             null, 1256233720, 1, '-submit',     1),
-        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 0, '', '', '', 1256233790, 2, 1, 'todo',             null, 1256233720, 1, '-_triesleft', 1),
-        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 0, '', '', '', 1256233790, 3, 2, 'todo',             null, 1256233740, 1, '-tryagain',   1),
-        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 0, '', '', '', 1256233790, 5, 3, 'gradedright',      null, 1256233790, 1, 'answer',     'frog'),
-        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 0, '', '', '', 1256233790, 5, 3, 'gradedright', 1.0000000, 1256233790, 1, '-submit',     1),
+        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 1, 0, 'todo',             null, 1256233700, 1, '-_triesleft', 3),
+        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 2, 1, 'todo',             null, 1256233720, 1, 'answer',     'toad'),
+        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 2, 1, 'todo',             null, 1256233720, 1, '-submit',     1),
+        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 2, 1, 'todo',             null, 1256233720, 1, '-_triesleft', 1),
+        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 3, 2, 'todo',             null, 1256233740, 1, '-tryagain',   1),
+        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 5, 3, 'gradedright',      null, 1256233790, 1, 'answer',     'frog'),
+        array(1, 1, 'unit_test', 'interactive', 1, 123, 1, 1, 'interactive', -1, 1, 1.0000000, 0.0000000, 1.0000000, 0, '', '', '', 1256233790, 5, 3, 'gradedright', 1.0000000, 1256233790, 1, '-submit',     1),
         );
     }
 
index 5807c02..c6bffa0 100644 (file)
@@ -137,6 +137,7 @@ abstract class question_behaviour_attempt_updater {
         $qa->rightanswer = $this->qtypeupdater->right_answer($this->question);
         $qa->maxmark = $this->question->maxmark;
         $qa->minfraction = 0;
+        $qa->maxfraction = 1;
         $qa->flagged = 0;
         $qa->responsesummary = '';
         $qa->timemodified = 0;
index 7287a5c..f8de4ee 100644 (file)
@@ -226,6 +226,7 @@ $technical = array();
 $technical[] = get_string('behaviourbeingused', 'question',
         question_engine::get_behaviour_name($qa->get_behaviour_name()));
 $technical[] = get_string('technicalinfominfraction',     'question', $qa->get_min_fraction());
+$technical[] = get_string('technicalinfomaxfraction',     'question', $qa->get_max_fraction());
 $technical[] = get_string('technicalinfoquestionsummary', 'question', s($qa->get_question_summary()));
 $technical[] = get_string('technicalinforightsummary',    'question', s($qa->get_right_answer_summary()));
 $technical[] = get_string('technicalinfostate',           'question', '' . $qa->get_state());
index 83e547b..3dcca15 100644 (file)
@@ -204,6 +204,7 @@ class qtype_calculated_attempt_upgrader_test extends question_attempt_upgrader_t
             'variant' => 10,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is 7.5 m + 4.9 m?
 
@@ -427,6 +428,7 @@ Remember to type a unit.',
             'variant' => 11,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is 5.1 m + 4.5 m?
 
@@ -657,6 +659,7 @@ Remember to type a unit.',
             'variant' => 1,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is 9.9 m + 2.5 m?
 
index 14c07eb..88bba90 100644 (file)
@@ -231,6 +231,7 @@ class qtype_calculatedmulti_attempt_upgrader_test extends question_attempt_upgra
             'variant' => 3,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is 4.3 + 5.4?',
             'rightanswer' => '9.7',
@@ -464,6 +465,7 @@ class qtype_calculatedmulti_attempt_upgrader_test extends question_attempt_upgra
             'variant' => 8,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is 3.7 + 6.0?',
             'rightanswer' => '9.7',
@@ -741,6 +743,7 @@ class qtype_calculatedmulti_attempt_upgrader_test extends question_attempt_upgra
             'variant' => 7,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is 4.4 + 8.2?',
             'rightanswer' => '12.6',
index f98be94..414879d 100644 (file)
@@ -195,6 +195,7 @@ class qtype_calculatedsimple_attempt_upgrader_test extends question_attempt_upgr
             'variant' => 7,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is 3 + 6 ?',
             'rightanswer' => '9',
@@ -405,6 +406,7 @@ class qtype_calculatedsimple_attempt_upgrader_test extends question_attempt_upgr
             'variant' => 4,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is 6.4 + 9 ?',
             'rightanswer' => '15.4',
@@ -607,6 +609,7 @@ class qtype_calculatedsimple_attempt_upgrader_test extends question_attempt_upgr
             'variant' => 6,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is 6.1 + 7 ?',
             'rightanswer' => '13.1',
index cd8dcc3..552269f 100644 (file)
@@ -157,6 +157,7 @@ class qtype_description_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'The following questions are based on the Northampton Art Gallery case study and associated web links. The questions cover artists and works that were available during the study weeks for Block 3. Some items may no longer be available on websites but will be available in the readings for Block 3.',
             'rightanswer' => '',
@@ -303,6 +304,7 @@ class qtype_description_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 0,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "PERSONAL AND PROFESSIONAL INFORMATION\n\nHere we want you to enter personal information and outline your professional qualifications and experience to date.",
             'rightanswer' => '',
@@ -439,6 +441,7 @@ class qtype_description_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 0,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "MUSIC TEACHING AND LEARNING \n\nIn this section we ask you to audit your knowledge, skills and understanding against the key issues covered by the non-core online and face-to-face module units. You will be invited to identify your strengths and provide evidence of your experience and understanding.\n\nIn this set of questions, you should select from the drop-down menu ‘None’, ‘Some’, ‘Good’ or ‘Strong’.",
             'rightanswer' => '',
index 122d753..19750b6 100644 (file)
@@ -218,6 +218,7 @@ class qtype_essay_attempt_upgrader_test extends question_attempt_upgrader_test_b
             'variant' => 1,
             'maxmark' => 2,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "* Give two examples of facilities within XML schemas that cannot be found in Document Type Definitions (DTDs).\n_(2 marks)_",
             'rightanswer' => '',
@@ -417,6 +418,7 @@ class qtype_essay_attempt_upgrader_test extends question_attempt_upgrader_test_b
             'variant' => 1,
             'maxmark' => 0,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "If you answered ‘No’ to the previous question please expand on your problem here.",
             'rightanswer' => '',
@@ -545,6 +547,7 @@ class qtype_essay_attempt_upgrader_test extends question_attempt_upgrader_test_b
             'variant' => 1,
             'maxmark' => 0,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "If you answered ‘No’ to the previous question please expand on your problem here.",
             'rightanswer' => '',
index 3f1a53d..ac76973 100644 (file)
@@ -224,6 +224,7 @@ class qtype_match_attempt_upgrader_test extends question_attempt_upgrader_test_b
             'variant' => 1,
             'maxmark' => 3,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'Associate the appropriate definition with each term. ' .
                     '{Active adjacent system; Autonomous adjacent system; ' .
@@ -455,6 +456,7 @@ class qtype_match_attempt_upgrader_test extends question_attempt_upgrader_test_b
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'Which of the following statements about subject ' .
                     'gateways are true, and which are false? {Subject gateways ' .
@@ -731,6 +733,7 @@ class qtype_match_attempt_upgrader_test extends question_attempt_upgrader_test_b
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'Which of the following statements about subject gateways are true, and which are false? ' .
                     '{Subject gateways provide links to sites that have been quality checked; ' .
index 3be216e..6e5e3c4 100644 (file)
@@ -112,6 +112,16 @@ class qtype_multianswer_question extends question_graded_automatically_with_coun
         return $fractionsum / $fractionmax;
     }
 
+    public function get_max_fraction() {
+        $fractionsum = 0;
+        $fractionmax = 0;
+        foreach ($this->subquestions as $i => $subq) {
+            $fractionmax += $subq->defaultmark;
+            $fractionsum += $subq->defaultmark * $subq->get_max_fraction();
+        }
+        return $fractionsum / $fractionmax;
+    }
+
     public function get_expected_data() {
         $expected = array();
         foreach ($this->subquestions as $i => $subq) {
index 7650457..66dacff 100644 (file)
@@ -205,6 +205,7 @@ class qtype_multianswer_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'An answer _____.',
             'rightanswer' => 'part 1: frog',
@@ -397,6 +398,7 @@ class qtype_multianswer_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'An answer _____.',
             'rightanswer' => 'part 1: frog',
@@ -604,6 +606,7 @@ class qtype_multianswer_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'An answer _____.',
             'rightanswer' => 'part 1: frog',
@@ -1273,6 +1276,7 @@ class qtype_multianswer_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => '13.0000000',
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'This question consists of some text with an answer embedded right here {Wrong answer; Another wrong answer; Correct answer; Answer that gives half the credit}
 
@@ -1947,6 +1951,7 @@ b) What grade would you give it? _____',
             'variant' => 1,
             'maxmark' => 13.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'This question consists of some text with an answer embedded right here {Wrong answer; Another wrong answer; Correct answer; Answer that gives half the credit}
 
@@ -2641,6 +2646,7 @@ b) What grade would you give it? _____',
             'variant' => 1,
             'maxmark' => '13.0000000',
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'This question consists of some text with an answer embedded right here {Wrong answer; Another wrong answer; Correct answer; Answer that gives half the credit}
 
index bc69407..cd30bc2 100644 (file)
@@ -239,6 +239,7 @@ class qtype_multichoice_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'Which is the amphibian?',
             'rightanswer' => 'Frog',
@@ -415,6 +416,7 @@ class qtype_multichoice_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'Why were standards such an important driver in the growth of systems integration?',
             'rightanswer' => 'Because they enable stored data and interfaces to be standardised.',
@@ -610,6 +612,7 @@ class qtype_multichoice_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'I have demonstrated the ability to analyse and ANSWER THE QUESTION that is asked. (Click for advice on this skill)',
             'rightanswer' => '',
@@ -833,6 +836,7 @@ class qtype_multichoice_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 5,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'Which of the following techniques can identify non-functional requirements?',
             'rightanswer' => 'Verb identification.; Misuse cases.',
@@ -991,6 +995,7 @@ class qtype_multichoice_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'Why were standards such an important driver in the growth of systems integration?',
             'rightanswer' => 'Because they enable stored data and interfaces to be standardised.',
@@ -1185,6 +1190,7 @@ public function test_multichoice_deferredfeedback_qsession140() {
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'Where will the 19th International Biology Olympiad be held?',
             'rightanswer' => 'Mumbai, India',
@@ -1423,6 +1429,7 @@ public function test_multichoice_deferredfeedback_qsession140() {
             'variant' => 1,
             'maxmark' => 0,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'Which was the most useful K315 information literacy or ICT activity?',
             'rightanswer' => 'Values Exchange case studies',
@@ -1655,6 +1662,7 @@ public function test_multichoice_deferredfeedback_qsession140() {
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "For source 3, the 'Loose Change' video, select the statements to indicate 'yes':",
             'rightanswer' => 'Would you regard this source as objective?; Does the source provide references?; Are all viewpoints considered?; Are quotations placed in their full context?; Does the source include conclusions based on evidence?; Would you trust this source?; Has it been peer-reviewed?',
@@ -1884,6 +1892,7 @@ public function test_multichoice_deferredfeedback_qsession140() {
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'Can we have a \'realist\' or objective social science?',
             'rightanswer' => 'Sometimes',
@@ -2097,6 +2106,7 @@ public function test_multichoice_deferredfeedback_qsession140() {
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "Read the text below and then answer the question based on the information given.\n\n我大哥没有我二哥高,我比我二哥高。\n\nWho is the tallest?",
             'rightanswer' => '我。',
@@ -2312,6 +2322,7 @@ public function test_multichoice_deferredfeedback_qsession140() {
             'variant' => 1,
             'maxmark' => 5,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is SOAP?',
             'rightanswer' => 'It is the transport mechanism used with web services.',
@@ -2521,6 +2532,7 @@ public function test_multichoice_deferredfeedback_qsession140() {
             'variant' => 1,
             'maxmark' => 0,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => '[CUT]',
             'rightanswer' => 'Well developed',
@@ -2732,6 +2744,7 @@ public function test_multichoice_deferredfeedback_qsession140() {
             'variant' => 1,
             'maxmark' => 0,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "USING THE INTERNET \n\nMany study resources are available online, and you will also be expected to find things out yourself using the web. \n\n_How would you rate your skills in using browsers and managing documents you find on the internet? _",
             'rightanswer' => 'Well developed',
index 0429480..b44c1e1 100644 (file)
@@ -229,6 +229,7 @@ class qtype_numerical_attempt_upgrader_test extends question_attempt_upgrader_te
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "Calculate your answer to the nearest WHOLE £ and enter it in the blank space provided. \n\n[Note: Please _DO NOT_ enter commas, spaces or £ signs within the number you enter.]  \n\nThe cash flows of a project are set out below: \n\n \t\tYEAR \n \t\t£ \n\n \t\tYear 0 \n \t\t(28,000) \n\n \t\tYear 1 \n \t\t18,000 \n\n \t\tYear 2 \n \t\t16,000 \n\nUsing the Table in Book 11, what is the project's net present value using a discount rate of 10%?  \n\nIf it is negative, put a minus sign before the number you enter.  \n\n£",
             'rightanswer' => '1586',
@@ -426,6 +427,7 @@ class qtype_numerical_attempt_upgrader_test extends question_attempt_upgrader_te
             'variant' => 1,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is twice 1.5 m?',
             'rightanswer' => '3 m',
index 130abad..e4566fa 100644 (file)
@@ -231,12 +231,24 @@ abstract class question_definition {
      * This method returns the lowest mark the question can return, on the
      * fraction scale. that is, where the maximum possible mark is 1.0.
      *
-     * @return number minimum fraction this question will ever return.
+     * @return float minimum fraction this question will ever return.
      */
     public function get_min_fraction() {
         return 0;
     }
 
+    /**
+     * Some questions can return a mark greater than the maximum.
+     *
+     * This method returns the lowest highest the question can return, on the
+     * fraction scale. that is, where the nominal maximum mark is 1.0.
+     *
+     * @return float maximum fraction this question will ever return.
+     */
+    public function get_max_fraction() {
+        return 1;
+    }
+
     /**
      * Given a response, rest the parts that are wrong.
      * @param array $response a response
@@ -521,11 +533,11 @@ interface question_automatically_gradable extends question_manually_gradable {
 
     /**
      * Grade a response to the question, returning a fraction between
-     * get_min_fraction() and 1.0, and the corresponding {@link question_state}
+     * get_min_fraction() and get_max_fraction(), and the corresponding {@link question_state}
      * right, partial or wrong.
      * @param array $response responses, as returned by
      *      {@link question_attempt_step::get_qt_data()}.
-     * @return array (number, integer) the fraction, and the state.
+     * @return array (float, integer) the fraction, and the state.
      */
     public function grade_response(array $response);
 
index a76531d..450c10b 100644 (file)
@@ -232,6 +232,7 @@ class qtype_random_attempt_upgrader_test extends question_attempt_upgrader_test_
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "(Notice in the panel at the left that the question you have just done is now greyed out. Remember that you can REVISIT ANY QUESTIONS by clicking on the NUMBERED BOXES. Click Q1 now to try this out and then click Q2 to return here.) \n\n[Table 1 showing Number of households receiving home care (England)] \n\n(LINK TO RESIZABLE TABLE 1)  \n\nWhich was the first year when more than a quarter of a million households received care from independent agencies?",
             'rightanswer' => '2005',
@@ -473,6 +474,7 @@ class qtype_random_attempt_upgrader_test extends question_attempt_upgrader_test_
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'En France, le covoiturage est une pratique qui a été au départ préconisé par « les écolos et les verts », mais depuis, elle :',
             'rightanswer' => 'n’est plus uniquement un positionnement écologiste.',
@@ -751,6 +753,7 @@ class qtype_random_attempt_upgrader_test extends question_attempt_upgrader_test_
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "The figure below shows a graph for converting between miles and kilometres. \n\n[ The graph has a horizontal axis, labelled miles, with a scale marked from 0 to 50 in steps of 5, and a vertical axis, labelled kilometres, with a scale from 0 to 80 in steps of 10. The straight line of the graph starts at the origin and slopes up to the right, and appears to pass through the point corresponding to 25 miles and 40 kilometres, and through the point corresponding to 50 miles and 80 kilometres. ] \n\nBy taking a reading from the graph, estimate how many kilometres are equivalent to 40 miles. \n\nRound your answer to the nearest kilometre and type it in the box below. \n\n(Your answer should be a single number, without units.)",
             'rightanswer' => '64 km',
@@ -948,6 +951,7 @@ class qtype_random_attempt_upgrader_test extends question_attempt_upgrader_test_
             'variant' => 1,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'What is twice 1.5 m?',
             'rightanswer' => '3 m',
index 162e294..be6e46c 100644 (file)
@@ -213,6 +213,7 @@ class qtype_shortanswer_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "Complete the following sentence. \n\nIn general, the procedures for analysing cost data for decision making are:  \n\nIgnore all sunk costs, ignore all ______ costs, use remaining costs for decision making purposes.",
             'rightanswer' => 'unavoidable*',
@@ -395,6 +396,7 @@ class qtype_shortanswer_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'In information-oriented integration what is the document which describes all the data structures in a potential integrated system and their relationships, for example, the fact that one database contained on a server will consist of a subset of another database contained in another server?',
             'rightanswer' => '*Enterprise data model*',
@@ -595,6 +597,7 @@ class qtype_shortanswer_attempt_upgrader_test extends question_attempt_upgrader_
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "Complete the following sentence by providing an appropriate word for the indicated gap. \n\nCapital investment appraisal involves both quantitative and ______ issues.",
             'rightanswer' => 'qualitative*',
index 315ec36..36f632b 100644 (file)
@@ -193,6 +193,7 @@ class qtype_truefalse_attempt_upgrader_test extends question_attempt_upgrader_te
             'variant' => 1,
             'maxmark' => 5,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'The term ‘integration server’ is another name for an application server, true or false?',
             'rightanswer' => 'False',
@@ -380,6 +381,7 @@ class qtype_truefalse_attempt_upgrader_test extends question_attempt_upgrader_te
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => "[my market] \n\nWhat can you buy in this shop? Is this list accurate? \n\nMark true or false (for the list as a whole). \n\n_single tickets_ \n\n_weekly season tickets_ \n\n_monthly season tickets_ \n\n_wine and grappa_ \n\n_fruit and vegetables_ \n\n_tobacco _",
             'rightanswer' => 'False',
@@ -549,6 +551,7 @@ class qtype_truefalse_attempt_upgrader_test extends question_attempt_upgrader_te
             'variant' => 1,
             'maxmark' => 1,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => 'Web services, integration servers, XML, application servers, message-oriented middleware and remote procedure call can be used to enable integrated systems?',
             'rightanswer' => 'True',
@@ -738,6 +741,7 @@ class qtype_truefalse_attempt_upgrader_test extends question_attempt_upgrader_te
             'variant' => 1,
             'maxmark' => 10.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => '1 +1 = 2 ?',
             'rightanswer' => 'True',
@@ -929,6 +933,7 @@ class qtype_truefalse_attempt_upgrader_test extends question_attempt_upgrader_te
             'variant' => 1,
             'maxmark' => 10.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => '1 +1 = 2 ?',
             'rightanswer' => 'True',
@@ -1125,6 +1130,7 @@ class qtype_truefalse_attempt_upgrader_test extends question_attempt_upgrader_te
             'variant' => 1,
             'maxmark' => 1.0000000,
             'minfraction' => 0,
+            'maxfraction' => 1,
             'flagged' => 0,
             'questionsummary' => '',
             'rightanswer' => 'True',
index 7f9a43a..9415705 100644 (file)
@@ -29,7 +29,7 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$version  = 2013100400.00;              // YYYYMMDD      = weekly release date of this DEV branch.
+$version  = 2013100400.01;              // YYYYMMDD      = weekly release date of this DEV branch.
                                         //         RR    = release increments - 00 in DEV branches.
                                         //           .XX = incremental changes.