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