Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are 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  /**
  18   * Tests of the upgrade to the new Moodle question engine for attempts at
  19   * truefalse questions.
  20   *
  21   * @package    qtype
  22   * @subpackage truefalse
  23   * @copyright  2009 The Open University
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  
  30  global $CFG;
  31  require_once($CFG->dirroot . '/question/engine/upgrade/tests/helper.php');
  32  
  33  
  34  /**
  35   * Testing the upgrade of truefalse question attempts.
  36   *
  37   * @copyright  2009 The Open University
  38   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  39   */
  40  class qtype_truefalse_attempt_upgrader_test extends question_attempt_upgrader_test_base {
  41  
  42      public function test_truefalse_deferredfeedback_history620() {
  43          $quiz = (object) array(
  44              'id' => '203',
  45              'course' => '2359',
  46              'name' => 'Quiz 1',
  47              'intro' => '',
  48              'introformat' => FORMAT_HTML,
  49              'timeopen' => '0',
  50              'timeclose' => '0',
  51              'preferredbehaviour' => 'deferredfeedback',
  52              'attempts' => '0',
  53              'attemptonlast' => '1',
  54              'grademethod' => '1',
  55              'decimalpoints' => '2',
  56              'review' => '71760879',
  57              'questionsperpage' => '2',
  58              'questiondecimalpoints' => '-1',
  59              'showuserpicture' => '1',
  60              'showblocks' => '1',
  61              'shufflequestions' => '0',
  62              'shuffleanswers' => '0',
  63              'sumgrades' => '50',
  64              'grade' => '50',
  65              'timecreated' => '0',
  66              'timemodified' => '1176461532',
  67              'password' => '',
  68              'subnet' => '',
  69              'popup' => '0',
  70              'delay1' => '0',
  71              'delay2' => '0',
  72              'timelimit' => '0',
  73          );
  74          $attempt = (object) array(
  75              'id' => '3795',
  76              'uniqueid' => '3795',
  77              'quiz' => '203',
  78              'userid' => '1888',
  79              'attempt' => '1',
  80              'sumgrades' => '40',
  81              'timestart' => '1177841172',
  82              'timefinish' => '1177841409',
  83              'timemodified' => '1177841394',
  84              'layout' => '3859,3860,0,3861,3862,0,3863,3864,0,3865,3866,0,3867,3868,0',
  85              'preview' => '0',
  86          );
  87          $question = (object) array(
  88              'id' => '3865',
  89              'category' => '187',
  90              'parent' => '0',
  91              'name' => 'Question 7',
  92              'questiontext' => '<p>The term ‘integration server’ is another name for an application server, true or false?</p>',
  93              'questiontextformat' => '1',
  94              'defaultmark' => '1',
  95              'penalty' => '0',
  96              'qtype' => 'truefalse',
  97              'length' => '1',
  98              'stamp' => 'learn.open.ac.uk+070404143040+oLimmG',
  99              'version' => 'learn.open.ac.uk+070405112705+DLhORU',
 100              'hidden' => '0',
 101              'generalfeedback' => '<p></p>',
 102              'generalfeedbackformat' => '1',
 103              'timecreated' => '0',
 104              'timemodified' => '0',
 105              'createdby' => null,
 106              'modifiedby' => null,
 107              'unlimited' => null,
 108              'maxmark' => '5',
 109              'options' => (object) array(
 110                  'id' => '98',
 111                  'question' => '3865',
 112                  'trueanswer' => '11693',
 113                  'falseanswer' => '11694',
 114                  'answers' => array(
 115                      11693 => (object) array(
 116                          'question' => '3865',
 117                          'answer' => 'True',
 118                          'fraction' => '0',
 119                          'feedback' => '',
 120                          'id' => 11693,
 121                      ),
 122                      11694 => (object) array(
 123                          'question' => '3865',
 124                          'answer' => 'False',
 125                          'fraction' => '1',
 126                          'feedback' => '',
 127                          'id' => 11694,
 128                      ),
 129                  ),
 130              ),
 131              'hints' => false,
 132          );
 133          $qsession = (object) array(
 134              'id' => '35137',
 135              'attemptid' => '3795',
 136              'questionid' => '3865',
 137              'newest' => '84791',
 138              'newgraded' => '84791',
 139              'sumpenalty' => '0',
 140              'manualcomment' => '',
 141              'manualcommentformat' => '1',
 142              'flagged' => '1',
 143          );
 144          $qstates = array(
 145              84771 => (object) array(
 146                  'attempt' => '3795',
 147                  'question' => '3865',
 148                  'originalquestion' => '0',
 149                  'seq_number' => '0',
 150                  'answer' => '',
 151                  'timestamp' => '1177841172',
 152                  'event' => '0',
 153                  'grade' => '0',
 154                  'raw_grade' => '0',
 155                  'penalty' => '0',
 156                  'id' => 84771,
 157              ),
 158              84785 => (object) array(
 159                  'attempt' => '3795',
 160                  'question' => '3865',
 161                  'originalquestion' => '0',
 162                  'seq_number' => '1',
 163                  'answer' => '11694',
 164                  'timestamp' => '1177841361',
 165                  'event' => '2',
 166                  'grade' => '0',
 167                  'raw_grade' => '5',
 168                  'penalty' => '5',
 169                  'id' => 84785,
 170              ),
 171              84791 => (object) array(
 172                  'attempt' => '3795',
 173                  'question' => '3865',
 174                  'originalquestion' => '0',
 175                  'seq_number' => '2',
 176                  'answer' => '11694',
 177                  'timestamp' => '1177841361',
 178                  'event' => '6',
 179                  'grade' => '5',
 180                  'raw_grade' => '5',
 181                  'penalty' => '5',
 182                  'id' => 84791,
 183              ),
 184          );
 185  
 186          $qa = $this->updater->convert_question_attempt($quiz, $attempt, $question, $qsession, $qstates);
 187  
 188          $expectedqa = (object) array(
 189              'behaviour' => 'deferredfeedback',
 190              'questionid' => 3865,
 191              'variant' => 1,
 192              'maxmark' => 5,
 193              'minfraction' => 0,
 194              'maxfraction' => 1,
 195              'flagged' => 0,
 196              'questionsummary' => 'The term ‘integration server’ is another name for an application server, true or false?',
 197              'rightanswer' => 'False',
 198              'responsesummary' => 'False',
 199              'timemodified' => 1177841361,
 200              'steps' => array(
 201                  0 => (object) array(
 202                      'sequencenumber' => 0,
 203                      'state' => 'todo',
 204                      'fraction' => null,
 205                      'timecreated' => 1177841172,
 206                      'userid' => 1888,
 207                      'data' => array(),
 208                  ),
 209                  1 => (object) array(
 210                      'sequencenumber' => 1,
 211                      'state' => 'complete',
 212                      'fraction' => null,
 213                      'timecreated' => 1177841361,
 214                      'userid' => 1888,
 215                      'data' => array('answer' => 0),
 216                  ),
 217                  2 => (object) array(
 218                      'sequencenumber' => 2,
 219                      'state' => 'gradedright',
 220                      'fraction' => 1,
 221                      'timecreated' => 1177841361,
 222                      'userid' => 1888,
 223                      'data' => array('answer' => 0, '-finish' => 1),
 224                  ),
 225              ),
 226          );
 227  
 228          $this->compare_qas($expectedqa, $qa);
 229      }
 230  
 231      public function test_truefalse_deferredfeedback_history20() {
 232          $quiz = (object) array(
 233              'id' => '551',
 234              'course' => '2828',
 235              'name' => 'Unit 4 Quiz',
 236              'intro' => '',
 237              'introformat' => FORMAT_HTML,
 238              'questiondecimalpoints' => '-1',
 239              'showuserpicture' => '1',
 240              'showblocks' => '1',
 241              'timeopen' => '0',
 242              'timeclose' => '0',
 243              'preferredbehaviour' => 'deferredfeedback',
 244              'attempts' => '0',
 245              'attemptonlast' => '0',
 246              'grademethod' => '1',
 247              'decimalpoints' => '2',
 248              'review' => '71760879',
 249              'questionsperpage' => '1',
 250              'shufflequestions' => '0',
 251              'shuffleanswers' => '1',
 252              'sumgrades' => '4',
 253              'grade' => '4',
 254              'timecreated' => '0',
 255              'timemodified' => '1190277883',
 256              'password' => '',
 257              'subnet' => '',
 258              'popup' => '0',
 259              'delay1' => '0',
 260              'delay2' => '0',
 261              'timelimit' => '0',
 262          );
 263          $attempt = (object) array(
 264              'id' => '23226',
 265              'uniqueid' => '23226',
 266              'quiz' => '551',
 267              'userid' => '80300',
 268              'attempt' => '2',
 269              'sumgrades' => '0',
 270              'timestart' => '1200326384',
 271              'timefinish' => '0',
 272              'timemodified' => '1200326384',
 273              'layout' => '9043,0,9057,0,9062,0,9241,0',
 274              'preview' => '0',
 275          );
 276          $question = (object) array(
 277              'id' => '9062',
 278              'category' => '481',
 279              'parent' => '0',
 280              'name' => 'U04_NA_In viaggio_Q3',
 281              'questiontext' => '<p><img title="my market" height="336" alt="my market" hspace="0" src="http://learnacct.open.ac.uk/file.php/2828/Naples_My_market.jpg" /></p>
 282          <p>What can you buy in this shop? Is this list accurate?</p>
 283          <p><br />Mark true or false (for the list as a whole).</p>
 284  
 285  
 286          <p><i>single tickets</i></p>
 287          <p><i>weekly season tickets</i></p>
 288          <p><i>monthly season tickets</i></p>
 289          <p><i>wine and grappa</i></p>
 290          <p><i>fruit and vegetables</i></p>
 291          <p><i>tobacco </i></p>',
 292              'questiontextformat' => '1',
 293              'defaultmark' => '1',
 294              'penalty' => '0',
 295              'qtype' => 'truefalse',
 296              'length' => '1',
 297              'stamp' => 'learn.open.ac.uk+070820163735+PqUlDM',
 298              'version' => 'learn.open.ac.uk+080304160318+owhQUb',
 299              'hidden' => '0',
 300              'generalfeedback' => '',
 301              'generalfeedbackformat' => '1',
 302              'timecreated' => '0',
 303              'timemodified' => '1204646598',
 304              'createdby' => null,
 305              'modifiedby' => '97230',
 306              'unlimited' => '0',
 307              'maxmark' => '1',
 308              'options' => (object) array(
 309                  'id' => '199',
 310                  'question' => '9062',
 311                  'trueanswer' => '28221',
 312                  'falseanswer' => '28222',
 313                  'answers' => array(
 314                      28221 => (object) array(
 315                          'question' => '9062',
 316                          'answer' => 'True',
 317                          'fraction' => '0',
 318                          'feedback' => '<p>The correct answer is \'false\'.  The only items on the list not sold at My Market are tobacco and weekly season tickets. It sells everything else! <br /><em>Biglietto unico</em> is a single ticket for bus, funicular railway or metro (underground) while <em>abbonamento mensile</em> is a monthly season ticket.<br />The shop also sells wine and grappa, as you can see them in the window, and fruit and vegetables as it says in the sign. Small shops in Naples often sell a variety of things, not always connected! </p>',
 319                          'id' => 28221,
 320                      ),
 321                      28222 => (object) array(
 322                          'question' => '9062',
 323                          'answer' => 'False',
 324                          'fraction' => '1',
 325                          'feedback' => 'The correct anstwer is \'false\'. The only items on the list not sold at My Market are tobacco and weekly season tickets. It sells everything else! <em>Biglietto</em> <em>unico</em> is a single ticket for bus, funicular railway or metro (underground) while \'abbonamento mensile\' is a monthly season ticket. It also sells wine and grappa, as you can see them in the window, and fruit and vegetables as it says in the sign! Small shops in Naples often sell a variety of things, not always connected! ',
 326                          'id' => 28222,
 327                      ),
 328                  ),
 329              ),
 330              'hints' => false,
 331          );
 332          $qsession = (object) array(
 333              'id' => '351032',
 334              'attemptid' => '23226',
 335              'questionid' => '9062',
 336              'newest' => '848428',
 337              'newgraded' => '848426',
 338              'sumpenalty' => '0',
 339              'manualcomment' => '',
 340              'manualcommentformat' => '1',
 341              'flagged' => '1',
 342          );
 343          $qstates = array(
 344              848426 => (object) array(
 345                  'attempt' => '23226',
 346                  'question' => '9062',
 347                  'originalquestion' => '0',
 348                  'seq_number' => '0',
 349                  'answer' => '',
 350                  'timestamp' => '1200326384',
 351                  'event' => '0',
 352                  'grade' => '0',
 353                  'raw_grade' => '0',
 354                  'penalty' => '0',
 355                  'id' => 848426,
 356              ),
 357              848428 => (object) array(
 358                  'attempt' => '23226',
 359                  'question' => '9062',
 360                  'originalquestion' => '0',
 361                  'seq_number' => '1',
 362                  'answer' => '28221',
 363                  'timestamp' => '1200326384',
 364                  'event' => '2',
 365                  'grade' => '0',
 366                  'raw_grade' => '0',
 367                  'penalty' => '1',
 368                  'id' => 848428,
 369              ),
 370          );
 371  
 372          $qa = $this->updater->convert_question_attempt($quiz, $attempt, $question, $qsession, $qstates);
 373  
 374          $expectedqa = (object) array(
 375              'behaviour' => 'deferredfeedback',
 376              'questionid' => 9062,
 377              'variant' => 1,
 378              'maxmark' => 1,
 379              'minfraction' => 0,
 380              'maxfraction' => 1,
 381              'flagged' => 0,
 382              '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 _",
 383              'rightanswer' => 'False',
 384              'responsesummary' => 'True',
 385              'timemodified' => 1200326384,
 386              'steps' => array(
 387                  0 => (object) array(
 388                      'sequencenumber' => 0,
 389                      'state' => 'todo',
 390                      'fraction' => null,
 391                      'timecreated' => 1200326384,
 392                      'userid' => 80300,
 393                      'data' => array(),
 394                  ),
 395                  1 => (object) array(
 396                      'sequencenumber' => 1,
 397                      'state' => 'complete',
 398                      'fraction' => null,
 399                      'timecreated' => 1200326384,
 400                      'userid' => 80300,
 401                      'data' => array('answer' => 1),
 402                  ),
 403              ),
 404          );
 405  
 406          $this->compare_qas($expectedqa, $qa);
 407      }
 408  
 409      public function test_truefalse_deferredfeedback_history90() {
 410          $quiz = (object) array(
 411              'id' => '3',
 412              'course' => '1095',
 413              'name' => 'Introduction quiz',
 414              'intro' => 'Use this self-assessment quiz after you have read the course introduction. ',
 415              'introformat' => FORMAT_HTML,
 416              'questiondecimalpoints' => '-1',
 417              'showuserpicture' => '1',
 418              'showblocks' => '1',
 419              'timeopen' => '1150107000',
 420              'timeclose' => '0',
 421              'preferredbehaviour' => 'deferredfeedback',
 422              'attempts' => '0',
 423              'attemptonlast' => '0',
 424              'grademethod' => '1',
 425              'decimalpoints' => '2',
 426              'review' => '71760879',
 427              'questionsperpage' => '0',
 428              'shufflequestions' => '1',
 429              'shuffleanswers' => '1',
 430              'sumgrades' => '9',
 431              'grade' => '9',
 432              'timecreated' => '0',
 433              'timemodified' => '1150127779',
 434              'password' => '',
 435              'subnet' => '',
 436              'popup' => '0',
 437              'delay1' => '0',
 438              'delay2' => '0',
 439              'timelimit' => '0',
 440          );
 441          $attempt = (object) array(
 442              'id' => '19',
 443              'uniqueid' => '19',
 444              'quiz' => '3',
 445              'userid' => '49542',
 446              'attempt' => '1',
 447              'sumgrades' => '9',
 448              'timestart' => '1150301292',
 449              'timefinish' => '1150301347',
 450              'timemodified' => '1150454872',
 451              'layout' => '96,108,102,101,106,113,104,98,111,0',
 452              'preview' => '0',
 453          );
 454          $question = (object) array(
 455              'id' => '111',
 456              'category' => '5',
 457              'parent' => '0',
 458              'name' => 'Q7',
 459              'questiontext' => 'Web services, integration servers, XML, application servers, message-oriented middleware and remote procedure call can be used to enable integrated systems?',
 460              'questiontextformat' => '1',
 461              'defaultgrade' => '1',
 462              'penalty' => '0',
 463              'qtype' => 'truefalse',
 464              'length' => '1',
 465              'stamp' => 'learn.open.ac.uk+060612113518+uuFWow',
 466              'version' => 'learn.open.ac.uk+060612154736+HeFOV0',
 467              'hidden' => '0',
 468              'generalfeedback' => '',
 469              'generalfeedbackformat' => '1',
 470              'timecreated' => '0',
 471              'timemodified' => '0',
 472              'createdby' => null,
 473              'modifiedby' => null,
 474              'unlimited' => null,
 475              'maxmark' => '1',
 476              'options' => (object) array(
 477                  'id' => '24',
 478                  'question' => '111',
 479                  'trueanswer' => '312',
 480                  'falseanswer' => '313',
 481                  'answers' => array(
 482                      312 => (object) array(
 483                          'question' => '111',
 484                          'answer' => 'True',
 485                          'fraction' => '1',
 486                          'feedback' => 'They are all used in storing data or connecting together components of an integrated system.',
 487                          'id' => 312,
 488                      ),
 489                      313 => (object) array(
 490                          'question' => '111',
 491                          'answer' => 'False',
 492                          'fraction' => '0',
 493                          'feedback' => 'They are all used in storing data or connecting together components of an integrated system.',
 494                          'id' => 313,
 495                      ),
 496                  ),
 497              ),
 498              'hints' => false,
 499          );
 500          $qsession = (object) array(
 501              'id' => '169',
 502              'attemptid' => '19',
 503              'questionid' => '111',
 504              'newest' => '252',
 505              'newgraded' => '252',
 506              'sumpenalty' => '0',
 507              'manualcomment' => '',
 508              'manualcommentformat' => '1',
 509              'flagged' => '1',
 510          );
 511          $qstates = array(
 512              242 => (object) array(
 513                  'attempt' => '19',
 514                  'question' => '111',
 515                  'originalquestion' => '0',
 516                  'seq_number' => '0',
 517                  'answer' => '',
 518                  'timestamp' => '1150301292',
 519                  'event' => '0',
 520                  'grade' => '0',
 521                  'raw_grade' => '0',
 522                  'penalty' => '0',
 523                  'id' => 242,
 524              ),
 525              252 => (object) array(
 526                  'attempt' => '19',
 527                  'question' => '111',
 528                  'originalquestion' => '0',
 529                  'seq_number' => '1',
 530                  'answer' => '',
 531                  'timestamp' => '1150454872',
 532                  'event' => '9',
 533                  'grade' => '1',
 534                  'raw_grade' => '1',
 535                  'penalty' => '0',
 536                  'id' => 252,
 537              ),
 538          );
 539  
 540          $qa = $this->updater->convert_question_attempt($quiz, $attempt, $question, $qsession, $qstates);
 541  
 542          $expectedqa = (object) array(
 543              'behaviour' => 'deferredfeedback',
 544              'questionid' => 111,
 545              'variant' => 1,
 546              'maxmark' => 1,
 547              'minfraction' => 0,
 548              'maxfraction' => 1,
 549              'flagged' => 0,
 550              'questionsummary' => 'Web services, integration servers, XML, application servers, message-oriented middleware and remote procedure call can be used to enable integrated systems?',
 551              'rightanswer' => 'True',
 552              'responsesummary' => '',
 553              'timemodified' => 1150454872,
 554              'steps' => array(
 555                  0 => (object) array(
 556                      'sequencenumber' => 0,
 557                      'state' => 'todo',
 558                      'fraction' => null,
 559                      'timecreated' => 1150301292,
 560                      'userid' => 49542,
 561                      'data' => array(),
 562                  ),
 563                  1 => (object) array(
 564                      'sequencenumber' => 1,
 565                      'state' => 'gradedwrong',
 566                      'fraction' => null,
 567                      'timecreated' => 1150454872,
 568                      'userid' => 49542,
 569                      'data' => array('-finish' => 1),
 570                  ),
 571                  2 => (object) array(
 572                      'sequencenumber' => 2,
 573                      'state' => 'mangrright',
 574                      'fraction' => 1,
 575                      'timecreated' => 1150454872,
 576                      'userid' => null,
 577                      'data' => array('-comment' => '', '-maxmark' => 1, '-mark' => 1),
 578                  ),
 579              ),
 580          );
 581  
 582          $this->compare_qas($expectedqa, $qa);
 583      }
 584  
 585      public function test_truefalse_adaptive_qsession119() {
 586          $quiz = (object) array(
 587              'id' => '6',
 588              'course' => '3',
 589              'name' => 'Simply quiz',
 590              'intro' => '<p>One quiz with 1 true/false Q</p>',
 591              'introformat' => '1',
 592              'timeopen' => '0',
 593              'timeclose' => '0',
 594              'attempts' => '0',
 595              'attemptonlast' => '0',
 596              'grademethod' => '1',
 597              'decimalpoints' => '2',
 598              'questiondecimalpoints' => '-1',
 599              'review' => '4459503',
 600              'questionsperpage' => '1',
 601              'shufflequestions' => '0',
 602              'shuffleanswers' => '1',
 603              'sumgrades' => '10.00000',
 604              'grade' => '10.00000',
 605              'timecreated' => '0',
 606              'timemodified' => '1309103209',
 607              'timelimit' => '0',
 608              'password' => '',
 609              'subnet' => '',
 610              'popup' => '0',
 611              'delay1' => '0',
 612              'delay2' => '0',
 613              'showuserpicture' => '0',
 614              'showblocks' => '0',
 615              'preferredbehaviour' => 'adaptive',
 616          );
 617          $attempt = (object) array(
 618              'id' => '20',
 619              'uniqueid' => '20',
 620              'quiz' => '6',
 621              'userid' => '7',
 622              'attempt' => '1',
 623              'sumgrades' => '10.00000',
 624              'timestart' => '1309103112',
 625              'timefinish' => '1309103120',
 626              'timemodified' => '1309103120',
 627              'layout' => '30,0',
 628              'preview' => '0',
 629          );
 630          $question = (object) array(
 631              'id' => '30',
 632              'category' => '10',
 633              'parent' => '0',
 634              'name' => '1 + 1 = 2 ?',
 635              'questiontext' => '<p>1 +1 = 2 ?</p>',
 636              'questiontextformat' => '1',
 637              'generalfeedback' => '<p>this is general feedback</p>',
 638              'generalfeedbackformat' => '1',
 639              'penalty' => '1.0000000',
 640              'qtype' => 'truefalse',
 641              'length' => '1',
 642              'stamp' => '127.0.0.1+110626154410+wFrWwP',
 643              'version' => '127.0.0.1+110626154410+u7CoaA',
 644              'hidden' => '0',
 645              'timecreated' => '1309103050',
 646              'timemodified' => '1309103050',
 647              'createdby' => '6',
 648              'modifiedby' => '6',
 649              'maxmark' => '10.0000000',
 650              'options' => (object) array(
 651                  'id' => '4',
 652                  'question' => '30',
 653                  'trueanswer' => '53',
 654                  'falseanswer' => '54',
 655                  'answers' => array(
 656                      53 => (object) array(
 657                          'id' => '53',
 658                          'question' => '30',
 659                          'answer' => 'True',
 660                          'answerformat' => '0',
 661                          'fraction' => '1.0000000',
 662                          'feedback' => '<p>this is correct (for true) feedback</p>',
 663                          'feedbackformat' => '1',
 664                      ),
 665                      54 => (object) array(
 666                          'id' => '54',
 667                          'question' => '30',
 668                          'answer' => 'False',
 669                          'answerformat' => '0',
 670                          'fraction' => '0.0000000',
 671                          'feedback' => '<p>this is incorrect (for false) feedback</p>',
 672                          'feedbackformat' => '1',
 673                      ),
 674                  ),
 675              ),
 676              'defaultmark' => '1.0000000',
 677          );
 678          $qsession = (object) array(
 679              'id' => '119',
 680              'attemptid' => '20',
 681              'questionid' => '30',
 682              'newest' => '312',
 683              'newgraded' => '312',
 684              'sumpenalty' => '10.0000000',
 685              'manualcomment' => '',
 686              'manualcommentformat' => '1',
 687              'flagged' => '0',
 688          );
 689          $qstates = array(
 690              310 => (object) array(
 691                  'id' => '310',
 692                  'attempt' => '20',
 693                  'question' => '30',
 694                  'seq_number' => '0',
 695                  'answer' => '',
 696                  'timestamp' => '1309103112',
 697                  'event' => '0',
 698                  'grade' => '0.0000000',
 699                  'raw_grade' => '0.0000000',
 700                  'penalty' => '0.0000000',
 701              ),
 702              311 => (object) array(
 703                  'id' => '311',
 704                  'attempt' => '20',
 705                  'question' => '30',
 706                  'seq_number' => '1',
 707                  'answer' => '53',
 708                  'timestamp' => '1309103115',
 709                  'event' => '3',
 710                  'grade' => '10.0000000',
 711                  'raw_grade' => '10.0000000',
 712                  'penalty' => '10.0000000',
 713              ),
 714              312 => (object) array(
 715                  'id' => '312',
 716                  'attempt' => '20',
 717                  'question' => '30',
 718                  'seq_number' => '1',
 719                  'answer' => '53',
 720                  'timestamp' => '1309103115',
 721                  'event' => '6',
 722                  'grade' => '10.0000000',
 723                  'raw_grade' => '10.0000000',
 724                  'penalty' => '10.0000000',
 725              ),
 726          );
 727  
 728          $qa = $this->updater->convert_question_attempt($quiz, $attempt, $question, $qsession, $qstates);
 729  
 730          $expectedqa = (object) array(
 731              'behaviour' => 'adaptive',
 732              'questionid' => 30,
 733              'variant' => 1,
 734              'maxmark' => 10.0000000,
 735              'minfraction' => 0,
 736              'maxfraction' => 1,
 737              'flagged' => 0,
 738              'questionsummary' => '1 +1 = 2 ?',
 739              'rightanswer' => 'True',
 740              'responsesummary' => 'True',
 741              'timemodified' => 1309103115,
 742              'steps' => array(
 743                  0 => (object) array(
 744                      'sequencenumber' => 0,
 745                      'state' => 'todo',
 746                      'fraction' => null,
 747                      'timecreated' => 1309103112,
 748                      'userid' => 7,
 749                      'data' => array(),
 750                  ),
 751                  1 => (object) array(
 752                      'sequencenumber' => 1,
 753                      'state' => 'complete',
 754                      'fraction' => 1.0,
 755                      'timecreated' => 1309103115,
 756                      'userid' => 7,
 757                      'data' => array('answer' => '1', '-_try' => '1',
 758                              '-_rawfraction' => '1', '-submit' => '1'),
 759                  ),
 760                  2 => (object) array(
 761                      'sequencenumber' => 2,
 762                      'state' => 'gradedright',
 763                      'fraction' => 1.0,
 764                      'timecreated' => 1309103115,
 765                      'userid' => 7,
 766                      'data' => array('answer' => '1', '-_try' => '1',
 767                              '-_rawfraction' => '1', '-finish' => '1'),
 768                  ),
 769              ),
 770          );
 771  
 772          $this->compare_qas($expectedqa, $qa);
 773      }
 774  
 775      public function test_truefalse_adaptive_qsession120() {
 776          $quiz = (object) array(
 777              'id' => '6',
 778              'course' => '3',
 779              'name' => 'Simply quiz',
 780              'intro' => '<p>One quiz with 1 true/false Q</p>',
 781              'introformat' => '1',
 782              'timeopen' => '0',
 783              'timeclose' => '0',
 784              'attempts' => '0',
 785              'attemptonlast' => '0',
 786              'grademethod' => '1',
 787              'decimalpoints' => '2',
 788              'questiondecimalpoints' => '-1',
 789              'review' => '4459503',
 790              'questionsperpage' => '1',
 791              'shufflequestions' => '0',
 792              'shuffleanswers' => '1',
 793              'sumgrades' => '10.00000',
 794              'grade' => '10.00000',
 795              'timecreated' => '0',
 796              'timemodified' => '1309103209',
 797              'timelimit' => '0',
 798              'password' => '',
 799              'subnet' => '',
 800              'popup' => '0',
 801              'delay1' => '0',
 802              'delay2' => '0',
 803              'showuserpicture' => '0',
 804              'showblocks' => '0',
 805              'preferredbehaviour' => 'adaptive',
 806          );
 807          $attempt = (object) array(
 808              'id' => '21',
 809              'uniqueid' => '21',
 810              'quiz' => '6',
 811              'userid' => '7',
 812              'attempt' => '2',
 813              'sumgrades' => '0.00000',
 814              'timestart' => '1309103130',
 815              'timefinish' => '1309103136',
 816              'timemodified' => '1309103136',
 817              'layout' => '30,0',
 818              'preview' => '0',
 819          );
 820          $question = (object) array(
 821              'id' => '30',
 822              'category' => '10',
 823              'parent' => '0',
 824              'name' => '1 + 1 = 2 ?',
 825              'questiontext' => '<p>1 +1 = 2 ?</p>',
 826              'questiontextformat' => '1',
 827              'generalfeedback' => '<p>this is general feedback</p>',
 828              'generalfeedbackformat' => '1',
 829              'penalty' => '1.0000000',
 830              'qtype' => 'truefalse',
 831              'length' => '1',
 832              'stamp' => '127.0.0.1+110626154410+wFrWwP',
 833              'version' => '127.0.0.1+110626154410+u7CoaA',
 834              'hidden' => '0',
 835              'timecreated' => '1309103050',
 836              'timemodified' => '1309103050',
 837              'createdby' => '6',
 838              'modifiedby' => '6',
 839              'maxmark' => '10.0000000',
 840              'options' => (object) array(
 841                  'id' => '4',
 842                  'question' => '30',
 843                  'trueanswer' => '53',
 844                  'falseanswer' => '54',
 845                  'answers' => array(
 846                      53 => (object) array(
 847                          'id' => '53',
 848                          'question' => '30',
 849                          'answer' => 'True',
 850                          'answerformat' => '0',
 851                          'fraction' => '1.0000000',
 852                          'feedback' => '<p>this is correct (for true) feedback</p>',
 853                          'feedbackformat' => '1',
 854                      ),
 855                      54 => (object) array(
 856                          'id' => '54',
 857                          'question' => '30',
 858                          'answer' => 'False',
 859                          'answerformat' => '0',
 860                          'fraction' => '0.0000000',
 861                          'feedback' => '<p>this is incorrect (for false) feedback</p>',
 862                          'feedbackformat' => '1',
 863                      ),
 864                  ),
 865              ),
 866              'defaultmark' => '1.0000000',
 867          );
 868          $qsession = (object) array(
 869              'id' => '120',
 870              'attemptid' => '21',
 871              'questionid' => '30',
 872              'newest' => '315',
 873              'newgraded' => '315',
 874              'sumpenalty' => '10.0000000',
 875              'manualcomment' => '',
 876              'manualcommentformat' => '1',
 877              'flagged' => '0',
 878          );
 879          $qstates = array(
 880              313 => (object) array(
 881                  'id' => '313',
 882                  'attempt' => '21',
 883                  'question' => '30',
 884                  'seq_number' => '0',
 885                  'answer' => '',
 886                  'timestamp' => '1309103130',
 887                  'event' => '0',
 888                  'grade' => '0.0000000',
 889                  'raw_grade' => '0.0000000',
 890                  'penalty' => '0.0000000',
 891              ),
 892              314 => (object) array(
 893                  'id' => '314',
 894                  'attempt' => '21',
 895                  'question' => '30',
 896                  'seq_number' => '1',
 897                  'answer' => '54',
 898                  'timestamp' => '1309103132',
 899                  'event' => '2',
 900                  'grade' => '0.0000000',
 901                  'raw_grade' => '0.0000000',
 902                  'penalty' => '10.0000000',
 903              ),
 904              315 => (object) array(
 905                  'id' => '315',
 906                  'attempt' => '21',
 907                  'question' => '30',
 908                  'seq_number' => '2',
 909                  'answer' => '54',
 910                  'timestamp' => '1309103132',
 911                  'event' => '6',
 912                  'grade' => '0.0000000',
 913                  'raw_grade' => '0.0000000',
 914                  'penalty' => '10.0000000',
 915              ),
 916          );
 917  
 918          $qa = $this->updater->convert_question_attempt($quiz, $attempt, $question, $qsession, $qstates);
 919  
 920          $expectedqa = (object) array(
 921              'behaviour' => 'adaptive',
 922              'questionid' => 30,
 923              'variant' => 1,
 924              'maxmark' => 10.0000000,
 925              'minfraction' => 0,
 926              'maxfraction' => 1,
 927              'flagged' => 0,
 928              'questionsummary' => '1 +1 = 2 ?',
 929              'rightanswer' => 'True',
 930              'responsesummary' => 'False',
 931              'timemodified' => 1309103132,
 932              'steps' => array(
 933                  0 => (object) array(
 934                      'sequencenumber' => 0,
 935                      'state' => 'todo',
 936                      'fraction' => null,
 937                      'timecreated' => 1309103130,
 938                      'userid' => 7,
 939                      'data' => array(),
 940                  ),
 941                  1 => (object) array(
 942                      'sequencenumber' => 1,
 943                      'state' => 'complete',
 944                      'fraction' => null,
 945                      'timecreated' => 1309103132,
 946                      'userid' => 7,
 947                      'data' => array('answer' => '0'),
 948                  ),
 949                  2 => (object) array(
 950                      'sequencenumber' => 2,
 951                      'state' => 'gradedwrong',
 952                      'fraction' => 0.0,
 953                      'timecreated' => 1309103132,
 954                      'userid' => 7,
 955                      'data' => array('answer' => 0, '-finish' => 1,
 956                              '-_try' => 1, '-_rawfraction' => 0),
 957                  ),
 958              ),
 959          );
 960  
 961          $this->compare_qas($expectedqa, $qa);
 962      }
 963  
 964      public function test_truefalse_adaptive_qsession3() {
 965          $quiz = (object) array(
 966              'id' => '1',
 967              'course' => '2',
 968              'name' => 'Test Quiz',
 969              'intro' => '',
 970              'introformat' => '1',
 971              'timeopen' => '0',
 972              'timeclose' => '0',
 973              'preferredbehaviour' => 'adaptive',
 974              'attempts' => '0',
 975              'attemptonlast' => '0',
 976              'grademethod' => '1',
 977              'decimalpoints' => '2',
 978              'questiondecimalpoints' => '-1',
 979              'reviewattempt' => '69888',
 980              'reviewcorrectness' => '69888',
 981              'reviewmarks' => '69888',
 982              'reviewspecificfeedback' => '69888',
 983              'reviewgeneralfeedback' => '69888',
 984              'reviewrightanswer' => '69888',
 985              'reviewoverallfeedback' => '4352',
 986              'questionsperpage' => '1',
 987              'shufflequestions' => '0',
 988              'shuffleanswers' => '1',
 989              'sumgrades' => '1.00000',
 990              'grade' => '10.00000',
 991              'timecreated' => '0',
 992              'timemodified' => '1309441728',
 993              'timelimit' => '0',
 994              'password' => '',
 995              'subnet' => '',
 996              'popup' => '0',
 997              'delay1' => '0',
 998              'delay2' => '0',
 999              'showuserpicture' => '0',
1000              'showblocks' => '0',
1001          );
1002          $attempt = (object) array(
1003              'id' => '3',
1004              'uniqueid' => '3',
1005              'quiz' => '1',
1006              'userid' => '4',
1007              'attempt' => '2',
1008              'sumgrades' => null,
1009              'timestart' => '1309441460',
1010              'timefinish' => '1309441471',
1011              'timemodified' => '1309441969',
1012              'layout' => '1,0',
1013              'preview' => '0',
1014          );
1015          $question = (object) array(
1016              'id' => '1',
1017              'category' => '2',
1018              'parent' => '0',
1019              'name' => 'Does 1 + 1 = 2?',
1020              'questiontext' => '',
1021              'questiontextformat' => '1',
1022              'generalfeedback' => '',
1023              'generalfeedbackformat' => '1',
1024              'defaultmark' => '1.0000000',
1025              'penalty' => '1.0000000',
1026              'qtype' => 'truefalse',
1027              'length' => '1',
1028              'stamp' => 'localhost:8888+110630134237+QzfsHZ',
1029              'version' => 'localhost:8888+110630134237+IaYGE6',
1030              'hidden' => '0',
1031              'timecreated' => '1309441357',
1032              'timemodified' => '1309441357',
1033              'createdby' => '3',
1034              'modifiedby' => '3',
1035              'maxmark' => '1.0000000',
1036              'options' => (object) array(
1037                  'id' => '1',
1038                  'question' => '1',
1039                  'trueanswer' => '1',
1040                  'falseanswer' => '2',
1041                  'answers' => array(
1042                      1 => (object) array(
1043                          'id' => '1',
1044                          'question' => '1',
1045                          'answer' => 'True',
1046                          'answerformat' => '0',
1047                          'fraction' => '1.0000000',
1048                          'feedback' => '',
1049                          'feedbackformat' => '1',
1050                      ),
1051                      2 => (object) array(
1052                          'id' => '2',
1053                          'question' => '1',
1054                          'answer' => 'False',
1055                          'answerformat' => '0',
1056                          'fraction' => '0.0000000',
1057                          'feedback' => '',
1058                          'feedbackformat' => '1',
1059                      ),
1060                  ),
1061              ),
1062          );
1063          $qsession = (object) array(
1064              'id' => '3',
1065              'attemptid' => '3',
1066              'questionid' => '1',
1067              'newest' => '7',
1068              'newgraded' => '7',
1069              'sumpenalty' => '1.0000000',
1070              'manualcomment' => '',
1071              'manualcommentformat' => '1',
1072              'flagged' => '0',
1073          );
1074          $qstates = array(
1075              5 => (object) array(
1076                  'id' => '5',
1077                  'attempt' => '3',
1078                  'question' => '1',
1079                  'seq_number' => '0',
1080                  'answer' => '',
1081                  'timestamp' => '1309441460',
1082                  'event' => '0',
1083                  'grade' => '0.0000000',
1084                  'raw_grade' => '0.0000000',
1085                  'penalty' => '0.0000000',
1086              ),
1087              6 => (object) array(
1088                  'id' => '6',
1089                  'attempt' => '3',
1090                  'question' => '1',
1091                  'seq_number' => '1',
1092                  'answer' => '1',
1093                  'timestamp' => '1309441463',
1094                  'event' => '3',
1095                  'grade' => '1.0000000',
1096                  'raw_grade' => '1.0000000',
1097                  'penalty' => '1.0000000',
1098              ),
1099              7 => (object) array(
1100                  'id' => '7',
1101                  'attempt' => '3',
1102                  'question' => '1',
1103                  'seq_number' => '1',
1104                  'answer' => '1',
1105                  'timestamp' => '1309441463',
1106                  'event' => '6',
1107                  'grade' => '1.0000000',
1108                  'raw_grade' => '1.0000000',
1109                  'penalty' => '1.0000000',
1110              ),
1111          );
1112  
1113          $qa = $this->updater->convert_question_attempt($quiz, $attempt, $question, $qsession, $qstates);
1114  
1115          $expectedqa = (object) array(
1116              'behaviour' => 'adaptive',
1117              'questionid' => 1,
1118              'variant' => 1,
1119              'maxmark' => 1.0000000,
1120              'minfraction' => 0,
1121              'maxfraction' => 1,
1122              'flagged' => 0,
1123              'questionsummary' => '',
1124              'rightanswer' => 'True',
1125              'responsesummary' => 'True',
1126              'timemodified' => 1309441463,
1127              'steps' => array(
1128                  0 => (object) array(
1129                      'sequencenumber' => 0,
1130                      'state' => 'todo',
1131                      'fraction' => null,
1132                      'timecreated' => 1309441460,
1133                      'userid' => 4,
1134                      'data' => array(),
1135                  ),
1136                  1 => (object) array(
1137                      'sequencenumber' => 1,
1138                      'state' => 'complete',
1139                      'fraction' => 1,
1140                      'timecreated' => 1309441463,
1141                      'userid' => 4,
1142                      'data' => array('answer' => 1, '-submit' => 1,
1143                              '-_try' => 1, '-_rawfraction' => 1),
1144                  ),
1145                  2 => (object) array(
1146                      'sequencenumber' => 2,
1147                      'state' => 'gradedright',
1148                      'fraction' => 1,
1149                      'timecreated' => 1309441463,
1150                      'userid' => 4,
1151                      'data' => array('answer' => 1, '-finish' => 1,
1152                              '-_try' => 1, '-_rawfraction' => 1),
1153                  ),
1154              ),
1155          );
1156  
1157          $this->compare_qas($expectedqa, $qa);
1158      }
1159  }