Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  namespace qtype_match;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  
  21  global $CFG;
  22  require_once($CFG->dirroot . '/question/engine/upgrade/tests/helper.php');
  23  
  24  
  25  /**
  26   * Testing the upgrade of match question attempts.
  27   *
  28   * @package   qtype_match
  29   * @copyright 2009 The Open University
  30   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  31   */
  32  class upgrade_old_attempt_data_test extends \question_attempt_upgrader_test_base {
  33  
  34      public function test_match_deferredfeedback_history6220() {
  35          $quiz = (object) array(
  36              'id' => '72',
  37              'course' => '1181',
  38              'name' => 'Study Guide 4 Quiz',
  39              'intro' => '',
  40              'introformat' => FORMAT_HTML,
  41              'questiondecimalpoints' => '-1',
  42              'showuserpicture' => '1',
  43              'showblocks' => '1',
  44              'timeopen' => '0',
  45              'timeclose' => '0',
  46              'preferredbehaviour' => 'deferredfeedback',
  47              'attempts' => '0',
  48              'attemptonlast' => '1',
  49              'grademethod' => '1',
  50              'decimalpoints' => '2',
  51              'review' => '71760879',
  52              'questionsperpage' => '2',
  53              'shufflequestions' => '0',
  54              'shuffleanswers' => '0',
  55              'sumgrades' => '48',
  56              'grade' => '48',
  57              'timecreated' => '0',
  58              'timemodified' => '1170427370',
  59              'password' => '',
  60              'subnet' => '',
  61              'popup' => '0',
  62              'delay1' => '0',
  63              'delay2' => '0',
  64              'timelimit' => '0',
  65          );
  66          $attempt = (object) array(
  67              'id' => '3562',
  68              'uniqueid' => '3562',
  69              'quiz' => '72',
  70              'userid' => '91483',
  71              'attempt' => '6',
  72              'sumgrades' => '43',
  73              'timestart' => '1177419915',
  74              'timefinish' => '1177419962',
  75              'timemodified' => '1168015476',
  76              'layout' => '689,690,0,691,692,0,693,694,0,695,696,0,697,698,0',
  77              'preview' => '0',
  78          );
  79          $question = (object) array(
  80              'id' => '695',
  81              'category' => '65',
  82              'parent' => '0',
  83              'name' => 'Question 7',
  84              'questiontext' => '<p>Associate the appropriate definition with each term.</p>',
  85              'questiontextformat' => '1',
  86              'defaultmark' => '1',
  87              'penalty' => '0',
  88              'qtype' => 'match',
  89              'length' => '1',
  90              'stamp' => 'learn.open.ac.uk+061123110024+a0RsuG',
  91              'version' => 'learn.open.ac.uk+061123163015+Oe63zC',
  92              'hidden' => '0',
  93              'generalfeedback' => 'For further information about this question see Study Guide 4 SAQ 3.1',
  94              'generalfeedbackformat' => '1',
  95              'timecreated' => '0',
  96              'timemodified' => '0',
  97              'createdby' => null,
  98              'modifiedby' => null,
  99              'unlimited' => null,
 100              'maxmark' => '3',
 101              'options' => (object) array(
 102                  'id' => '27',
 103                  'questionid' => '695',
 104                  'subquestions' => array(
 105                      148 => (object) array(
 106                          'questionid' => '695',
 107                          'questiontext' => 'Active adjacent system',
 108                          'answertext' => 'A system that interacts with or participates in the work.',
 109                          'id' => 148,
 110                      ),
 111                      149 => (object) array(
 112                          'questionid' => '695',
 113                          'questiontext' => 'Autonomous adjacent system',
 114                          'answertext' => 'An external entity that acts independently of the work under study.',
 115                          'id' => 149,
 116                      ),
 117                      150 => (object) array(
 118                          'questionid' => '695',
 119                          'questiontext' => 'Cooperative adjacent system',
 120                          'answertext' => 'A system that is involved in the response to a business event.',
 121                          'id' => 150,
 122                      ),
 123                      151 => (object) array(
 124                          'questionid' => '695',
 125                          'questiontext' => '',
 126                          'answertext' => 'A system which does not supply or receive data from the work.',
 127                          'id' => 151,
 128                      ),
 129                      152 => (object) array(
 130                          'questionid' => '695',
 131                          'questiontext' => '',
 132                          'answertext' => 'An external entity that performs part of the work under study.',
 133                          'id' => 152,
 134                      ),
 135                  ),
 136                  'shuffleanswers' => '1',
 137                  'correctfeedback' => '',
 138                  'partiallycorrectfeedback' => '',
 139                  'incorrectfeedback' => '',
 140                  'correctresponsesfeedback' => '0',
 141              ),
 142              'hints' => false,
 143          );
 144          $qsession = (object) array(
 145              'id' => '33092',
 146              'attemptid' => '3562',
 147              'questionid' => '695',
 148              'newest' => '79626',
 149              'newgraded' => '79626',
 150              'sumpenalty' => '0',
 151              'manualcomment' => '',
 152              'manualcommentformat' => '1',
 153              'flagged' => '1',
 154          );
 155          $qstates = array(
 156              79604 => (object) array(
 157                  'attempt' => '3562',
 158                  'question' => '695',
 159                  'originalquestion' => '0',
 160                  'seq_number' => '0',
 161                  'answer' => '148-0,149-0,150-0,151-0,152-0',
 162                  'timestamp' => '1177419915',
 163                  'event' => '0',
 164                  'grade' => '0',
 165                  'raw_grade' => '0',
 166                  'penalty' => '0',
 167                  'id' => 79604,
 168              ),
 169              79614 => (object) array(
 170                  'attempt' => '3562',
 171                  'question' => '695',
 172                  'originalquestion' => '0',
 173                  'seq_number' => '1',
 174                  'answer' => '148-148,149-151,150-152,151-0,152-0',
 175                  'timestamp' => '1177419855',
 176                  'event' => '2',
 177                  'grade' => '0',
 178                  'raw_grade' => '1',
 179                  'penalty' => '0',
 180                  'id' => 79614,
 181              ),
 182              79619 => (object) array(
 183                  'attempt' => '3562',
 184                  'question' => '695',
 185                  'originalquestion' => '0',
 186                  'seq_number' => '2',
 187                  'answer' => '148-148,149-149,150-150,151-0,152-0',
 188                  'timestamp' => '1177419956',
 189                  'event' => '2',
 190                  'grade' => '0',
 191                  'raw_grade' => '3',
 192                  'penalty' => '0',
 193                  'id' => 79619,
 194              ),
 195              79626 => (object) array(
 196                  'attempt' => '3562',
 197                  'question' => '695',
 198                  'originalquestion' => '0',
 199                  'seq_number' => '3',
 200                  'answer' => '148-148,149-149,150-150,151-0,152-0',
 201                  'timestamp' => '1177419956',
 202                  'event' => '6',
 203                  'grade' => '3',
 204                  'raw_grade' => '3',
 205                  'penalty' => '0',
 206                  'id' => 79626,
 207              ),
 208          );
 209  
 210          $qa = $this->updater->convert_question_attempt($quiz, $attempt, $question, $qsession, $qstates);
 211  
 212          $expectedqa = (object) array(
 213              'behaviour' => 'deferredfeedback',
 214              'questionid' => 695,
 215              'variant' => 1,
 216              'maxmark' => 3,
 217              'minfraction' => 0,
 218              'maxfraction' => 1,
 219              'flagged' => 0,
 220              'questionsummary' => 'Associate the appropriate definition with each term. ' .
 221                      '{Active adjacent system; Autonomous adjacent system; ' .
 222                      'Cooperative adjacent system} -> {A system that interacts with ' .
 223                      'or participates in the work.; An external entity that acts ' .
 224                      'independently of the work under study.; A system that is involved ' .
 225                      'in the response to a business event.; A system which does not supply ' .
 226                      'or receive data from the work.; An external entity that performs part ' .
 227                      'of the work under study.}',
 228              'rightanswer' => 'Active adjacent system -> A system that interacts with ' .
 229                      'or participates in the work.; Autonomous adjacent system -> ' .
 230                      'An external entity that acts independently of the work under study.; ' .
 231                      'Cooperative adjacent system -> A system that is involved in the response ' .
 232                      'to a business event.',
 233              'responsesummary' => 'Active adjacent system -> A system that interacts with ' .
 234                      'or participates in the work.; Autonomous adjacent system -> ' .
 235                      'An external entity that acts independently of the work under study.; ' .
 236                      'Cooperative adjacent system -> A system that is involved in the response ' .
 237                      'to a business event.',
 238              'timemodified' => 1177419956,
 239              'steps' => array(
 240                  0 => (object) array(
 241                      'sequencenumber' => 0,
 242                      'state' => 'todo',
 243                      'fraction' => null,
 244                      'timecreated' => 1177419915,
 245                      'userid' => 91483,
 246                      'data' => array('_stemorder' => '148,149,150',
 247                              '_choiceorder' => 'todo - see below'),
 248                  ),
 249                  1 => (object) array(
 250                      'sequencenumber' => 1,
 251                      'state' => 'complete',
 252                      'fraction' => null,
 253                      'timecreated' => 1177419855,
 254                      'userid' => 91483,
 255                      'data' => array('sub0' => 148, 'sub1' => 151, 'sub2' => 152),
 256                  ),
 257                  2 => (object) array(
 258                      'sequencenumber' => 2,
 259                      'state' => 'complete',
 260                      'fraction' => null,
 261                      'timecreated' => 1177419956,
 262                      'userid' => 91483,
 263                      'data' => array('sub0' => 148, 'sub1' => 149, 'sub2' => 150),
 264                  ),
 265                  3 => (object) array(
 266                      'sequencenumber' => 3,
 267                      'state' => 'gradedright',
 268                      'fraction' => 1,
 269                      'timecreated' => 1177419956,
 270                      'userid' => 91483,
 271                      'data' => array('sub0' => 148, 'sub1' => 149, 'sub2' => 150, '-finish' => 1),
 272                  ),
 273              ),
 274          );
 275  
 276          // This is a random thing, so just set expected to actual.
 277          $expectedqa->steps[0]->data['_choiceorder'] = $qa->steps[0]->data['_choiceorder'];
 278          $order = explode(',', $qa->steps[0]->data['_choiceorder']);
 279          $order = array_combine(array_values($order), array_keys($order));
 280          for ($i = 1; $i <= 3; $i++) {
 281              for ($sub = 0; $sub < 3; $sub++) {
 282                  $expectedqa->steps[$i]->data['sub' . $sub] =
 283                          $order[$expectedqa->steps[$i]->data['sub' . $sub]] + 1;
 284              }
 285          }
 286  
 287          $this->compare_qas($expectedqa, $qa);
 288      }
 289  
 290      public function test_match_deferredfeedback_history60() {
 291          $quiz = (object) array(
 292              'id' => '60',
 293              'course' => '2304',
 294              'name' => 'Types of resources available quiz',
 295              'intro' => 'This quiz covers the different types of information resources available ' .
 296                      'and how to select which is most appropriate. ',
 297              'introformat' => FORMAT_HTML,
 298              'questiondecimalpoints' => '-1',
 299              'showuserpicture' => '1',
 300              'showblocks' => '1',
 301              'timeopen' => '1164153600',
 302              'timeclose' => '1606003200',
 303              'preferredbehaviour' => 'deferredfeedback',
 304              'attempts' => '0',
 305              'attemptonlast' => '0',
 306              'grademethod' => '1',
 307              'decimalpoints' => '3',
 308              'review' => '71752557',
 309              'questionsperpage' => '1',
 310              'shufflequestions' => '0',
 311              'shuffleanswers' => '0',
 312              'sumgrades' => '5',
 313              'grade' => '10',
 314              'timecreated' => '0',
 315              'timemodified' => '1170245956',
 316              'password' => '',
 317              'subnet' => '',
 318              'popup' => '0',
 319              'delay1' => '0',
 320              'delay2' => '0',
 321              'timelimit' => '0',
 322          );
 323          $attempt = (object) array(
 324              'id' => '1065',
 325              'uniqueid' => '1065',
 326              'quiz' => '60',
 327              'userid' => '182682',
 328              'attempt' => '1',
 329              'sumgrades' => '3.99998',
 330              'timestart' => '1168267317',
 331              'timefinish' => '1168267508',
 332              'timemodified' => '1168267508',
 333              'layout' => '509,510,511,738,514,0',
 334              'preview' => '0',
 335          );
 336          $question = (object) array(
 337              'id' => '738',
 338              'category' => '60',
 339              'parent' => '0',
 340              'name' => 'TR004',
 341              'questiontext' => '<p>Which of the following statements about subject gateways are true, and which are false? </p>',
 342              'questiontextformat' => '1',
 343              'defaultmark' => '1',
 344              'penalty' => '0.1',
 345              'qtype' => 'match',
 346              'length' => '1',
 347              'stamp' => 'learn.open.ac.uk+061128151507+CLevuJ',
 348              'version' => 'learn.open.ac.uk+070108115531+VvJurj',
 349              'hidden' => '0',
 350              'generalfeedback' => '<UL><LI>Subject gateways provide links to sites that have been quality checked = True</LI>
 351          <LI>Subject gateways offer more variety than search engines = False</LI>
 352          <LI>Subject gateways index websites automatically = False</LI>
 353          <LI>Subject gateways can provide a more direct route to websites containing academic content = True</LI>
 354          </UL>',
 355              'generalfeedbackformat' => '1',
 356              'timecreated' => '0',
 357              'timemodified' => '0',
 358              'createdby' => null,
 359              'modifiedby' => null,
 360              'unlimited' => null,
 361              'maxmark' => '1',
 362              'options' => (object) array(
 363                  'id' => '35',
 364                  'questionid' => '738',
 365                  'subquestions' => array(
 366                      213 => (object) array(
 367                          'questionid' => '738',
 368                          'questiontext' => 'Subject gateways provide links to sites that have been quality checked ',
 369                          'answertext' => 'True',
 370                          'id' => 213,
 371                      ),
 372                      214 => (object) array(
 373                          'questionid' => '738',
 374                          'questiontext' => 'Subject gateways offer more variety than search engines ',
 375                          'answertext' => 'False',
 376                          'id' => 214,
 377                      ),
 378                      215 => (object) array(
 379                          'questionid' => '738',
 380                          'questiontext' => 'Subject gateways index websites automatically',
 381                          'answertext' => 'False',
 382                          'id' => 215,
 383                      ),
 384                      216 => (object) array(
 385                          'questionid' => '738',
 386                          'questiontext' => 'Subject gateways can provide a more direct route ' .
 387                                  'to websites containing academic content ',
 388                          'answertext' => 'True',
 389                          'id' => 216,
 390                      ),
 391                  ),
 392                  'shuffleanswers' => '1',
 393                  'correctfeedback' => '',
 394                  'partiallycorrectfeedback' => '',
 395                  'incorrectfeedback' => '',
 396                  'correctresponsesfeedback' => '0',
 397              ),
 398              'hints' => false,
 399          );
 400          $qsession = (object) array(
 401              'id' => '9258',
 402              'attemptid' => '1065',
 403              'questionid' => '738',
 404              'newest' => '24966',
 405              'newgraded' => '24966',
 406              'sumpenalty' => '0',
 407              'manualcomment' => '',
 408              'manualcommentformat' => '1',
 409              'flagged' => '1',
 410          );
 411          $qstates = array(
 412              24961 => (object) array(
 413                  'attempt' => '1065',
 414                  'question' => '738',
 415                  'originalquestion' => '0',
 416                  'seq_number' => '0',
 417                  'answer' => '213-0,214-0,215-0,216-0',
 418                  'timestamp' => '1168267317',
 419                  'event' => '0',
 420                  'grade' => '0',
 421                  'raw_grade' => '0',
 422                  'penalty' => '0',
 423                  'id' => 24961,
 424              ),
 425              24966 => (object) array(
 426                  'attempt' => '1065',
 427                  'question' => '738',
 428                  'originalquestion' => '0',
 429                  'seq_number' => '1',
 430                  'answer' => '213-213,214-214,215-215,216-216',
 431                  'timestamp' => '1168267508',
 432                  'event' => '6',
 433                  'grade' => '1',
 434                  'raw_grade' => '1',
 435                  'penalty' => '0.1',
 436                  'id' => 24966,
 437              ),
 438          );
 439  
 440          $qa = $this->updater->convert_question_attempt($quiz, $attempt, $question, $qsession, $qstates);
 441  
 442          $expectedqa = (object) array(
 443              'behaviour' => 'deferredfeedback',
 444              'questionid' => 738,
 445              'variant' => 1,
 446              'maxmark' => 1,
 447              'minfraction' => 0,
 448              'maxfraction' => 1,
 449              'flagged' => 0,
 450              'questionsummary' => 'Which of the following statements about subject ' .
 451                      'gateways are true, and which are false? {Subject gateways ' .
 452                      'provide links to sites that have been quality checked; ' .
 453                      'Subject gateways offer more variety than search engines; ' .
 454                      'Subject gateways index websites automatically; ' .
 455                      'Subject gateways can provide a more direct route to websites containing academic content} -> ' .
 456                      '{True; False}',
 457              'rightanswer' => 'Subject gateways provide links to sites that have been quality checked -> True; ' .
 458                      'Subject gateways offer more variety than search engines -> False; ' .
 459                      'Subject gateways index websites automatically -> False; ' .
 460                      'Subject gateways can provide a more direct route to websites containing academic content -> True',
 461              'responsesummary' => 'Subject gateways provide links to sites that have been quality checked -> True; ' .
 462                      'Subject gateways offer more variety than search engines -> False; ' .
 463                      'Subject gateways index websites automatically -> False; ' .
 464                      'Subject gateways can provide a more direct route to websites containing academic content -> True',
 465              'timemodified' => 1168267508,
 466              'steps' => array(
 467                  0 => (object) array(
 468                      'sequencenumber' => 0,
 469                      'state' => 'todo',
 470                      'fraction' => null,
 471                      'timecreated' => 1168267317,
 472                      'userid' => 182682,
 473                      'data' => array('_stemorder' => '213,214,215,216', '_choiceorder' => 'todo - see below'),
 474                  ),
 475                  1 => (object) array(
 476                      'sequencenumber' => 1,
 477                      'state' => 'gradedright',
 478                      'fraction' => 1,
 479                      'timecreated' => 1168267508,
 480                      'userid' => 182682,
 481                      'data' => array('sub0' => 213, 'sub1' => 214, 'sub2' => 214, 'sub3' => 213, '-finish' => 1),
 482                  ),
 483              ),
 484          );
 485  
 486          // This is a random thing, so just set expected to actual.
 487          $expectedqa->steps[0]->data['_choiceorder'] = $qa->steps[0]->data['_choiceorder'];
 488          $order = explode(',', $qa->steps[0]->data['_choiceorder']);
 489          $order = array_combine(array_values($order), array_keys($order));
 490          for ($i = 1; $i <= 1; $i++) {
 491              for ($sub = 0; $sub < 4; $sub++) {
 492                  $expectedqa->steps[$i]->data['sub' . $sub] =
 493                          $order[$expectedqa->steps[$i]->data['sub' . $sub]] + 1;
 494              }
 495          }
 496  
 497          $this->compare_qas($expectedqa, $qa);
 498      }
 499  
 500      public function test_match_deferredfeedback_history622220() {
 501          $quiz = (object) array(
 502              'id' => '719',
 503              'course' => '3541',
 504              'name' => 'Types of resources quiz',
 505              'intro' => '',
 506              'introformat' => FORMAT_HTML,
 507              'questiondecimalpoints' => '-1',
 508              'showuserpicture' => '1',
 509              'showblocks' => '1',
 510              'timeopen' => '0',
 511              'timeclose' => '0',
 512              'preferredbehaviour' => 'deferredfeedback',
 513              'attempts' => '0',
 514              'attemptonlast' => '0',
 515              'grademethod' => '1',
 516              'decimalpoints' => '2',
 517              'review' => '71760879',
 518              'questionsperpage' => '1',
 519              'shufflequestions' => '0',
 520              'shuffleanswers' => '1',
 521              'sumgrades' => '5',
 522              'grade' => '10',
 523              'timecreated' => '0',
 524              'timemodified' => '1193678199',
 525              'password' => '',
 526              'subnet' => '',
 527              'popup' => '0',
 528              'delay1' => '0',
 529              'delay2' => '0',
 530              'timelimit' => '0',
 531          );
 532          $attempt = (object) array(
 533              'id' => '23777',
 534              'uniqueid' => '23777',
 535              'quiz' => '719',
 536              'userid' => '6584',
 537              'attempt' => '1',
 538              'sumgrades' => '3.91664',
 539              'timestart' => '1200506648',
 540              'timefinish' => '1200507571',
 541              'timemodified' => '1200506959',
 542              'layout' => '11163,0,11164,0,11165,0,11135,0,11166,0',
 543              'preview' => '0',
 544          );
 545          $question = (object) array(
 546              'id' => '11135',
 547              'category' => '675',
 548              'parent' => '0',
 549              'name' => 'TR004',
 550              'questiontext' => '<p>Which of the following statements about subject gateways are true, and which are false? </p>',
 551              'questiontextformat' => '0',
 552              'defaultmark' => '1',
 553              'penalty' => '0.1',
 554              'qtype' => 'match',
 555              'length' => '1',
 556              'stamp' => 'learn.open.ac.uk+071023110917+tqaM6z',
 557              'version' => 'learn.open.ac.uk+071023110917+Ia7Hpz',
 558              'hidden' => '0',
 559              'generalfeedback' => '<ul>
 560              <li>Subject gateways provide links to sites that have been quality checked = True </li>
 561   </ul>
 562   <p>All links in a subject gateway have been added by a knowledgeable subject specialist and ' .
 563                                  'so have to be of a certain quality to be added to the collection.</p>
 564   <ul>
 565              <li>Subject gateways offer more variety than search engines = False </li>
 566   </ul>
 567   <p>Subject gateways will most likely provide fewer links than a search engine, but this is because ' .
 568                                  'they are selected with a particular subject area in mind </p>
 569   <ul>
 570              <li>Subject gateways index websites automatically = False </li>
 571   </ul>
 572   <p>Subject gateways links are indexed by knowledgeable subject specialists rather than a machine. </p>
 573   <ul>
 574              <li>Subject gateways can provide a more direct route to websites containing academic content = True </li>
 575   </ul>
 576   <p>All links in a subject gateway have been added by a knowledgeable subject specialist ' .
 577                                  'and so you can find academic content easier than using a web search engine.</p>',
 578              'generalfeedbackformat' => '1',
 579              'timecreated' => '0',
 580              'timemodified' => '0',
 581              'createdby' => null,
 582              'modifiedby' => null,
 583              'unlimited' => null,
 584              'maxmark' => '1',
 585              'options' => (object) array(
 586                  'id' => '279',
 587                  'questionid' => '11135',
 588                  'subquestions' => array(
 589                      1632 => (object) array(
 590                          'questionid' => '11135',
 591                          'questiontext' => 'Subject gateways provide links to sites that have been quality checked',
 592                          'answertext' => 'True',
 593                          'id' => 1632,
 594                      ),
 595                      1633 => (object) array(
 596                          'questionid' => '11135',
 597                          'questiontext' => 'Subject gateways offer more variety than search engines',
 598                          'answertext' => 'False',
 599                          'id' => 1633,
 600                      ),
 601                      1634 => (object) array(
 602                          'questionid' => '11135',
 603                          'questiontext' => 'Subject gateways index websites automatically',
 604                          'answertext' => 'False',
 605                          'id' => 1634,
 606                      ),
 607                      1635 => (object) array(
 608                          'questionid' => '11135',
 609                          'questiontext' => 'Subject gateways can provide a more direct route to websites ' .
 610                                  'containing academic content',
 611                          'answertext' => 'True',
 612                          'id' => 1635,
 613                      ),
 614                  ),
 615                  'shuffleanswers' => '1',
 616                  'correctfeedback' => '',
 617                  'partiallycorrectfeedback' => '',
 618                  'incorrectfeedback' => '',
 619                  'correctresponsesfeedback' => '0',
 620              ),
 621              'hints' => false,
 622          );
 623          $qsession = (object) array(
 624              'id' => '356418',
 625              'attemptid' => '23777',
 626              'questionid' => '11135',
 627              'newest' => '862740',
 628              'newgraded' => '862740',
 629              'sumpenalty' => '0.1',
 630              'manualcomment' => '',
 631              'manualcommentformat' => '1',
 632              'flagged' => '1',
 633          );
 634          $qstates = array(
 635              862587 => (object) array(
 636                  'attempt' => '23777',
 637                  'question' => '11135',
 638                  'originalquestion' => '0',
 639                  'seq_number' => '0',
 640                  'answer' => '1633-0,1635-0,1634-0,1632-0',
 641                  'timestamp' => '1200506648',
 642                  'event' => '0',
 643                  'grade' => '0',
 644                  'raw_grade' => '0',
 645                  'penalty' => '0',
 646                  'id' => 862587,
 647              ),
 648              862638 => (object) array(
 649                  'attempt' => '23777',
 650                  'question' => '11135',
 651                  'originalquestion' => '0',
 652                  'seq_number' => '1',
 653                  'answer' => '1633-1633,1635-1635,1634-0,1632-1632',
 654                  'timestamp' => '1200507025',
 655                  'event' => '2',
 656                  'grade' => '0',
 657                  'raw_grade' => '0.75',
 658                  'penalty' => '0.1',
 659                  'id' => 862638,
 660              ),
 661              862668 => (object) array(
 662                  'attempt' => '23777',
 663                  'question' => '11135',
 664                  'originalquestion' => '0',
 665                  'seq_number' => '2',
 666                  'answer' => '1633-1633,1635-1635,1634-0,1632-1632',
 667                  'timestamp' => '1200507125',
 668                  'event' => '2',
 669                  'grade' => '0',
 670                  'raw_grade' => '0.75',
 671                  'penalty' => '0.1',
 672                  'id' => 862668,
 673              ),
 674              862673 => (object) array(
 675                  'attempt' => '23777',
 676                  'question' => '11135',
 677                  'originalquestion' => '0',
 678                  'seq_number' => '3',
 679                  'answer' => '1633-1633,1635-1635,1634-0,1632-1632',
 680                  'timestamp' => '1200507172',
 681                  'event' => '2',
 682                  'grade' => '0',
 683                  'raw_grade' => '0.75',
 684                  'penalty' => '0.1',
 685                  'id' => 862673,
 686              ),
 687              862716 => (object) array(
 688                  'attempt' => '23777',
 689                  'question' => '11135',
 690                  'originalquestion' => '0',
 691                  'seq_number' => '4',
 692                  'answer' => '1633-1633,1635-1635,1634-1635,1632-1632',
 693                  'timestamp' => '1200507467',
 694                  'event' => '2',
 695                  'grade' => '0',
 696                  'raw_grade' => '0.75',
 697                  'penalty' => '0.1',
 698                  'id' => 862716,
 699              ),
 700              862740 => (object) array(
 701                  'attempt' => '23777',
 702                  'question' => '11135',
 703                  'originalquestion' => '0',
 704                  'seq_number' => '5',
 705                  'answer' => '1633-1633,1635-1635,1634-1635,1632-1632',
 706                  'timestamp' => '1200507467',
 707                  'event' => '6',
 708                  'grade' => '0.75',
 709                  'raw_grade' => '0.75',
 710                  'penalty' => '0.1',
 711                  'id' => 862740,
 712              ),
 713          );
 714  
 715          $qa = $this->updater->convert_question_attempt($quiz, $attempt, $question, $qsession, $qstates);
 716  
 717          $expectedqa = (object) array(
 718              'behaviour' => 'deferredfeedback',
 719              'questionid' => 11135,
 720              'variant' => 1,
 721              'maxmark' => 1,
 722              'minfraction' => 0,
 723              'maxfraction' => 1,
 724              'flagged' => 0,
 725              'questionsummary' => 'Which of the following statements about subject gateways are true, and which are false? ' .
 726                      '{Subject gateways provide links to sites that have been quality checked; ' .
 727                      'Subject gateways offer more variety than search engines; ' .
 728                      'Subject gateways index websites automatically; ' .
 729                      'Subject gateways can provide a more direct route to websites containing academic content} ' .
 730                      '-> {True; False}',
 731              'rightanswer' => 'Subject gateways provide links to sites that have been quality checked -> True; ' .
 732                      'Subject gateways offer more variety than search engines -> False; ' .
 733                      'Subject gateways index websites automatically -> False; ' .
 734                      'Subject gateways can provide a more direct route to websites containing academic content -> True',
 735              'responsesummary' => 'Subject gateways offer more variety than search engines -> False; ' .
 736                      'Subject gateways can provide a more direct route to websites containing academic content -> True; ' .
 737                      'Subject gateways index websites automatically -> True; ' .
 738                      'Subject gateways provide links to sites that have been quality checked -> True',
 739              'timemodified' => 1200507467,
 740              'steps' => array(
 741                  0 => (object) array(
 742                      'sequencenumber' => 0,
 743                      'state' => 'todo',
 744                      'fraction' => null,
 745                      'timecreated' => 1200506648,
 746                      'userid' => 6584,
 747                      'data' => array('_stemorder' => '1633,1635,1634,1632',
 748                              '_choiceorder' => 'todo - see below'),
 749                  ),
 750                  1 => (object) array(
 751                      'sequencenumber' => 1,
 752                      'state' => 'complete',
 753                      'fraction' => null,
 754                      'timecreated' => 1200507025,
 755                      'userid' => 6584,
 756                      'data' => array('sub0' => 1633, 'sub1' => 1632, 'sub2' => 0, 'sub3' => 1632),
 757                  ),
 758                  2 => (object) array(
 759                      'sequencenumber' => 2,
 760                      'state' => 'complete',
 761                      'fraction' => null,
 762                      'timecreated' => 1200507125,
 763                      'userid' => 6584,
 764                      'data' => array('sub0' => 1633, 'sub1' => 1632, 'sub2' => 0, 'sub3' => 1632),
 765                  ),
 766                  3 => (object) array(
 767                      'sequencenumber' => 3,
 768                      'state' => 'complete',
 769                      'fraction' => null,
 770                      'timecreated' => 1200507172,
 771                      'userid' => 6584,
 772                      'data' => array('sub0' => 1633, 'sub1' => 1632, 'sub2' => 0, 'sub3' => 1632),
 773                  ),
 774                  4 => (object) array(
 775                      'sequencenumber' => 4,
 776                      'state' => 'complete',
 777                      'fraction' => null,
 778                      'timecreated' => 1200507467,
 779                      'userid' => 6584,
 780                      'data' => array('sub0' => 1633, 'sub1' => 1632, 'sub2' => 1632, 'sub3' => 1632),
 781                  ),
 782                  5 => (object) array(
 783                      'sequencenumber' => 5,
 784                      'state' => 'gradedpartial',
 785                      'fraction' => 0.75,
 786                      'timecreated' => 1200507467,
 787                      'userid' => 6584,
 788                      'data' => array('sub0' => 1633, 'sub1' => 1632, 'sub2' => 1632, 'sub3' => 1632, '-finish' => 1),
 789                  ),
 790              ),
 791          );
 792  
 793          // This is a random thing, so just set expected to actual.
 794          $expectedqa->steps[0]->data['_choiceorder'] = $qa->steps[0]->data['_choiceorder'];
 795          $order = explode(',', $qa->steps[0]->data['_choiceorder']);
 796          $order = array_combine(array_values($order), array_keys($order));
 797          for ($i = 1; $i <= 5; $i++) {
 798              for ($sub = 0; $sub < 5; $sub++) {
 799                  if (!array_key_exists('sub' . $sub, $expectedqa->steps[$i]->data) ||
 800                          $expectedqa->steps[$i]->data['sub' . $sub] == 0) {
 801                      continue;
 802                  }
 803                  $expectedqa->steps[$i]->data['sub' . $sub] =
 804                          $order[$expectedqa->steps[$i]->data['sub' . $sub]] + 1;
 805              }
 806          }
 807  
 808          $this->compare_qas($expectedqa, $qa);
 809      }
 810  }