[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/mod/scorm/datamodels/ -> sequencinglib.php (source)

   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  function scorm_seq_exit_action_rules($seq, $userid) {
  18      $sco = $seq->currentactivity;
  19      $ancestors = scorm_get_ancestors($sco);
  20      $exittarget = null;
  21      foreach (array_reverse($ancestors) as $ancestor) {
  22          if (scorm_seq_rules_check($ancestor, 'exit') != null) {
  23              $exittarget = $ancestor;
  24              break;
  25          }
  26      }
  27      if ($exittarget != null) {
  28          $commons = array_slice($ancestors, 0, scorm_find_common_ancestor($ancestors, $exittarget));
  29  
  30          // Terminate Descendent Attempts Process.
  31          if ($commons) {
  32              foreach ($commons as $ancestor) {
  33                  scorm_seq_end_attempt($ancestor, $userid, $seq->attempt);
  34                  $seq->currentactivity = $ancestor;
  35              }
  36          }
  37      }
  38      return $seq;
  39  }
  40  
  41  function scorm_seq_post_cond_rules($seq, $userid) {
  42      $sco = $seq->currentactivity;
  43      if (!$seq->suspended) {
  44          if ($action = scorm_seq_rules_check($sco, 'post') != null) {
  45              switch($action) {
  46                  case 'retry':
  47                  case 'continue':
  48                  case 'previous':
  49                      $seq->sequencing = $action;
  50                  break;
  51                  case 'exitparent':
  52                  case 'exitall':
  53                      $seq->termination = $action;
  54                  break;
  55                  case 'retryall':
  56                      $seq->termination = 'exitall';
  57                      $seq->sequencing = 'retry';
  58                  break;
  59              }
  60          }
  61      }
  62      return $seq;
  63  }
  64  
  65  
  66  function scorm_seq_evaluate_rollupcond($sco, $conditioncombination, $rollupruleconds, $userid) {
  67      $bag = Array();
  68      $con = "";
  69      $val = false;
  70      $unk = false;
  71      foreach ($rollupruleconds as $rolluprulecond) {
  72          $condit = scorm_evaluate_condition($rolluprulecond, $sco, $userid);
  73          if ($rolluprulecond->operator == 'not') { // If operator is not, negate the condition.
  74              if ($rolluprulecond->cond != 'unknown') {
  75                  if ($condit) {
  76                      $condit = false;
  77                  } else {
  78                      $condit = true;
  79                  }
  80              } else {
  81                  $condit = 'unknown';
  82              }
  83              array_push($childrenbag, $condit);
  84          }
  85      }
  86      if (empty($bag)) {
  87          return 'unknown';
  88      } else {
  89          $i = 0;
  90          foreach ($bag as $b) {
  91              if ($rolluprulecond->conditioncombination == 'all') {
  92                  $val = true;
  93                  if ($b == 'unknown') {
  94                      $unk = true;
  95                  }
  96                  if ($b === false) {
  97                      return false;
  98                  }
  99              } else {
 100                  $val = false;
 101  
 102                  if ($b == 'unknown') {
 103                      $unk = true;
 104                  }
 105                  if ($b === true) {
 106                      return true;
 107                  }
 108              }
 109          }
 110      }
 111      if ($unk) {
 112          return 'unknown';
 113      }
 114      return $val;
 115  }
 116  
 117  function scorm_seq_check_child ($sco, $action, $userid) {
 118      global $DB;
 119  
 120      $included = false;
 121      $sco = scorm_get_sco($sco->id);
 122      $r = $DB->get_record('scorm_scoes_track', array('scoid' => $sco->id, 'userid' => $userid, 'element' => 'activityattemptcount'));
 123      if ($action == 'satisfied' || $action == 'notsatisfied') {
 124          if (!$sco->rollupobjectivesatisfied) {
 125              $included = true;
 126              if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifnotsuspended') ||
 127                  ($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifnotsuspended')) {
 128  
 129                  if (!scorm_seq_is('activityprogressstatus', $sco->id, $userid) ||
 130                      ((($r->value) > 0) && !scorm_seq_is('suspended', $sco->id, $userid))) {
 131                      $included = false;
 132                  }
 133  
 134              } else {
 135                  if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifattempted') ||
 136                      ($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifattempted')) {
 137                      if (!scorm_seq_is('activityprogressstatus', $sco->id, $userid) || (($r->value) == 0)) {
 138                          $included = false;
 139                      }
 140                  } else {
 141                      if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifnotskipped') ||
 142                          ($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifnotskipped')) {
 143                          $rulch = scorm_seq_rules_check($sco, 'skip');
 144                          if ($rulch != null) {
 145                              $included = false;
 146                          }
 147                      }
 148                  }
 149              }
 150          }
 151      }
 152      if ($action == 'completed' || $action == 'incomplete') {
 153          if (!$sco->rollupprogresscompletion) {
 154              $included = true;
 155  
 156              if (($action == 'completed' && $sco->requiredforcompleted == 'ifnotsuspended') ||
 157                  ($action == 'incomplete' && $sco->requiredforincomplete == 'ifnotsuspended')) {
 158  
 159                  if (!scorm_seq_is('activityprogressstatus', $sco->id, $userid) ||
 160                      ((($r->value) > 0)&& !scorm_seq_is('suspended', $sco->id, $userid))) {
 161                      $included = false;
 162                  }
 163  
 164              } else {
 165  
 166                  if (($action == 'completed' && $sco->requiredforcompleted == 'ifattempted') ||
 167                      ($action == 'incomplete' && $sco->requiredforincomplete == 'ifattempted')) {
 168                      if (!scorm_seq_is('activityprogressstatus', $sco->id, $userid) || (($r->value) == 0)) {
 169                          $included = false;
 170                      }
 171  
 172                  } else {
 173                      if (($action == 'completed' && $sco->requiredforsatisfied == 'ifnotskipped') ||
 174                          ($action == 'incomplete' && $sco->requiredfornotsatisfied == 'ifnotskipped')) {
 175                          $rulch = scorm_seq_rules_check($sco, 'skip');
 176                          if ($rulch != null) {
 177                              $included = false;
 178                          }
 179                      }
 180                  }
 181              }
 182          }
 183      }
 184      return $included;
 185  }
 186  
 187  function scorm_seq_sequencing ($scoid, $userid, $seq) {
 188  
 189      switch ($seq->sequencing) {
 190          case 'start':
 191              // We'll see the parameters we have to send, this should update delivery and end.
 192              $seq = scorm_seq_start_sequencing($scoid, $userid, $seq);
 193              $seq->sequencing = true;
 194              break;
 195  
 196          case 'resumeall':
 197              // We'll see the parameters we have to send, this should update delivery and end.
 198              $seq = scorm_seq_resume_all_sequencing($scoid, $userid, $seq);
 199              $seq->sequencing = true;
 200              break;
 201  
 202          case 'exit':
 203              // We'll see the parameters we have to send, this should update delivery and end.
 204              $seq = scorm_seq_exit_sequencing($scoid, $userid, $seq);
 205              $seq->sequencing = true;
 206              break;
 207  
 208          case 'retry':
 209              // We'll see the parameters we have to send, this should update delivery and end.
 210              $seq = scorm_seq_retry_sequencing($scoid, $userid, $seq);
 211              $seq->sequencing = true;
 212              break;
 213  
 214          case 'previous':
 215              // We'll see the parameters we have to send, this should update delivery and end.
 216              $seq = scorm_seq_previous_sequencing($scoid, $userid, $seq);
 217              $seq->sequencing = true;
 218              break;
 219  
 220          case 'choice':
 221              // We'll see the parameters we have to send, this should update delivery and end.
 222              $seq = scorm_seq_choice_sequencing($scoid, $userid, $seq);
 223              $seq->sequencing = true;
 224              break;
 225      }
 226  
 227      if ($seq->exception != null) {
 228          $seq->sequencing = false;
 229          return $seq;
 230      }
 231  
 232      $seq->sequencing = true;
 233      return $seq;
 234  }
 235  
 236  function scorm_seq_start_sequencing($scoid, $userid, $seq) {
 237      global $DB;
 238  
 239      if (!empty($seq->currentactivity)) {
 240          $seq->delivery = null;
 241          $seq->exception = 'SB.2.5-1';
 242          return $seq;
 243      }
 244      $sco = $DB->get_record('scorm_scoes', array('scoid' => $scoid, 'userid' => $userid));
 245      if (($sco->parent == '/') && scorm_is_leaf($sco)) { // If the activity is the root and is leaf.
 246          $seq->delivery = $sco;
 247      } else {
 248          $ancestors = scorm_get_ancestors($sco);
 249          $ancestorsroot = array_reverse($ancestors);
 250          $res = scorm_seq_flow($ancestorsroot[0], 'forward', $seq, true, $userid);
 251          if ($res) {
 252              return $res;
 253          }
 254      }
 255  }
 256  
 257  function scorm_seq_resume_all_sequencing($scoid, $userid, $seq) {
 258      global $DB;
 259  
 260      if (!empty($seq->currentactivity)) {
 261          $seq->delivery = null;
 262          $seq->exception = 'SB.2.6-1';
 263          return $seq;
 264      }
 265      $track = $DB->get_record('scorm_scoes_track', array('scoid' => $scoid, 'userid' => $userid, 'element' => 'suspendedactivity'));
 266      if (!$track) {
 267          $seq->delivery = null;
 268          $seq->exception = 'SB.2.6-2';
 269          return $seq;
 270      }
 271      // We assign the sco to the delivery.
 272      $seq->delivery = $DB->get_record('scorm_scoes', array('scoid' => $scoid, 'userid' => $userid));
 273  }
 274  
 275  function scorm_seq_continue_sequencing($scoid, $userid, $seq) {
 276      if (empty($seq->currentactivity)) {
 277          $seq->delivery = null;
 278          $seq->exception = 'SB.2.7-1';
 279          return $seq;
 280      }
 281      $currentact = $seq->currentactivity;
 282      if ($currentact->parent != '/') {
 283          // If the activity is the root and is leaf.
 284          $parent = scorm_get_parent ($currentact);
 285  
 286          if (!isset($parent->flow) || ($parent->flow == false)) {
 287              $seq->delivery = null;
 288              $seq->exception = 'SB.2.7-2';
 289              return $seq;
 290          }
 291  
 292          $res = scorm_seq_flow($currentact, 'forward', $seq, false, $userid);
 293          if ($res) {
 294              return $res;
 295          }
 296      }
 297  }
 298  
 299  function scorm_seq_previous_sequencing($scoid, $userid, $seq) {
 300      if (empty($seq->currentactivity)) {
 301          $seq->delivery = null;
 302          $seq->exception = 'SB.2.8-1';
 303          return $seq;
 304      }
 305  
 306      $currentact = $seq->currentactivity;
 307      if ($currentact->parent != '/') { // If the activity is the root and is leaf.
 308          $parent = scorm_get_parent ($currentact);
 309          if (!isset($parent->flow) || ($parent->flow == false)) {
 310              $seq->delivery = null;
 311              $seq->exception = 'SB.2.8-2';
 312              return $seq;
 313          }
 314  
 315          $res = scorm_seq_flow($currentact, 'backward', $seq, false, $userid);
 316          if ($res) {
 317              return $res;
 318          }
 319      }
 320  }
 321  
 322  function scorm_seq_exit_sequencing($scoid, $userid, $seq) {
 323      if (empty($seq->currentactivity)) {
 324          $seq->delivery = null;
 325          $seq->exception = 'SB.2.11-1';
 326          return $seq;
 327      }
 328  
 329      if ($seq->active) {
 330          $seq->endsession = false;
 331          $seq->exception = 'SB.2.11-2';
 332          return $seq;
 333      }
 334      $currentact = $seq->currentactivity;
 335      if ($currentact->parent == '/') {
 336          $seq->endsession = true;
 337          return $seq;
 338      }
 339  
 340      $seq->endsession = false;
 341      return $seq;
 342  }
 343  
 344  function scorm_seq_retry_sequencing($scoid, $userid, $seq) {
 345      if (empty($seq->currentactivity)) {
 346          $seq->delivery = null;
 347          $seq->exception = 'SB.2.10-1';
 348          return $seq;
 349      }
 350      if ($seq->active || $seq->suspended) {
 351          $seq->delivery = null;
 352          $seq->exception = 'SB.2.10-2';
 353          return $seq;
 354      }
 355  
 356      if (!scorm_is_leaf($seq->currentactivity)) {
 357          $res = scorm_seq_flow($seq->currentactivity, 'forward', $seq, true, $userid);
 358          if ($res != null) {
 359              return $res;
 360          } else {
 361              // Return deliver.
 362              $seq->delivery = null;
 363              $seq->exception = 'SB.2.10-3';
 364              return $seq;
 365          }
 366      } else {
 367          $seq->delivery = $seq->currentactivity;
 368          return $seq;
 369      }
 370  
 371  }
 372  
 373  function scorm_seq_choice_sequencing($sco, $userid, $seq) {
 374  
 375      $avchildren = Array ();
 376      $comancestor = null;
 377      $traverse = null;
 378  
 379      if ($sco == null) {
 380          $seq->delivery = null;
 381          $seq->exception = 'SB.2.9-1';
 382          return $seq;
 383      }
 384  
 385      $ancestors = scorm_get_ancestors($sco);
 386      $arrpath = array_reverse($ancestors);
 387      array_push ($arrpath, $sco); // Path from the root to the target.
 388  
 389      foreach ($arrpath as $activity) {
 390          if ($activity->parent != '/') {
 391              $avchildren = scorm_get_available_children (scorm_get_parent($activity));
 392              $position = array_search($avchildren, $activity);
 393              if ($position !== false) {
 394                  $seq->delivery = null;
 395                  $seq->exception = 'SB.2.9-2';
 396                  return $seq;
 397              }
 398          }
 399  
 400          if (scorm_seq_rules_check($activity, 'hidefromchoice' != null)) {
 401              $seq->delivery = null;
 402              $seq->exception = 'SB.2.9-3';
 403              return $seq;
 404          }
 405      }
 406  
 407      if ($sco->parent != '/') {
 408          $parent = scorm_sco_get_parent ($sco);
 409          if ( isset($parent->choice) && ($parent->choice == false)) {
 410              $seq->delivery = null;
 411              $seq->exception = 'SB.2.9-4';
 412              return $seq;
 413          }
 414      }
 415  
 416      if ($seq->currentactivity != null) {
 417          $commonpos = scorm_find_common_ancestor($ancestors, $seq->currentactivity);
 418          $comancestor = $arrpath [$commonpos];
 419      } else {
 420          $comancestor = $arrpath [0];
 421      }
 422  
 423      if ($seq->currentactivity === $sco) {
 424          break;
 425      }
 426  
 427      $sib = scorm_get_siblings($seq->currentactivity);
 428      $pos = array_search($sib, $sco);
 429  
 430      if ($pos !== false) {
 431          $siblings = array_slice($sib, 0, $pos - 1);
 432          if (empty($siblings)) {
 433              $seq->delivery = null;
 434              $seq->exception = 'SB.2.9-5';
 435              return $seq;
 436          }
 437  
 438          $children = scorm_get_children (scorm_get_parent ($sco));
 439          $pos1 = array_search($children, $sco);
 440          $pos2 = array_search($seq->currentactivity, $sco);
 441          if ($pos1 > $pos2) {
 442              $traverse = 'forward';
 443          } else {
 444              $traverse = 'backward';
 445          }
 446  
 447          foreach ($siblings as $sibling) {
 448              $seq = scorm_seq_choice_activity_traversal($sibling, $userid, $seq, $traverse);
 449              if (!$seq->reachable) {
 450                  $seq->delivery = null;
 451                  return $seq;
 452              }
 453          }
 454          break;
 455      }
 456  
 457      if ($seq->currentactivity == null || $seq->currentactivity == $comancestor) {
 458          $commonpos = scorm_find_common_ancestor($ancestors, $seq->currentactivity);
 459          // Path from the common ancestor to the target activity.
 460          $comtarget = array_slice($ancestors, 1, $commonpos - 1);
 461          $comtarget = array_reverse($comtarget);
 462  
 463          if (empty($comtarget)) {
 464              $seq->delivery = null;
 465              $seq->exception = 'SB.2.9-5';
 466              return $seq;
 467          }
 468          foreach ($comtarget as $act) {
 469              $seq = scorm_seq_choice_activity_traversal($act, $userid, $seq, 'forward');
 470              if (!$seq->reachable) {
 471                  $seq->delivery = null;
 472                  return $seq;
 473              }
 474              $act = scorm_get_sco ($acti->id);
 475              if (scorm_seq_is('active', $act->id, $userid) && ($act->id != $comancestor->id && $act->preventactivation)) {
 476                  $seq->delivery = null;
 477                  $seq->exception = 'SB.2.9-6';
 478                  return $seq;
 479              }
 480          }
 481          break;
 482      }
 483  
 484      if ($comancestor->id == $sco->id) {
 485  
 486          $ancestorscurrent = scorm_get_ancestors($seq->currentactivity);
 487          $possco = array_search($ancestorscurrent, $sco);
 488          // Path from the current activity to the target.
 489          $curtarget = array_slice($ancestorscurrent, 0, $possco);
 490  
 491          if (empty($curtarget)) {
 492              $seq->delivery = null;
 493              $seq->exception = 'SB.2.9-5';
 494              return $seq;
 495          }
 496          $i = 0;
 497          foreach ($curtarget as $activ) {
 498              $i++;
 499              if ($i != count($curtarget)) {
 500                  if (isset($activ->choiceexit) && ($activ->choiceexit == false)) {
 501                      $seq->delivery = null;
 502                      $seq->exception = 'SB.2.9-7';
 503                      return $seq;
 504                  }
 505              }
 506          }
 507          break;
 508      }
 509  
 510      if (array_search($ancestors, $comancestor) !== false) {
 511          $ancestorscurrent = scorm_get_ancestors($seq->currentactivity);
 512          $commonpos = scorm_find_common_ancestor($ancestors, $sco);
 513          $curcommon = array_slice($ancestorscurrent, 0, $commonpos - 1);
 514          if (empty($curcommon)) {
 515              $seq->delivery = null;
 516              $seq->exception = 'SB.2.9-5';
 517              return $seq;
 518          }
 519  
 520          $constrained = null;
 521          foreach ($curcommon as $acti) {
 522              $acti = scorm_get_sco($acti->id);
 523              if (isset($acti->choiceexit) && ($acti->choiceexit == false)) {
 524                      $seq->delivery = null;
 525                      $seq->exception = 'SB.2.9-7';
 526                      return $seq;
 527              }
 528              if ($constrained == null) {
 529                  if ($acti->constrainchoice == true) {
 530                      $constrained = $acti;
 531                  }
 532              }
 533          }
 534          if ($constrained != null) {
 535              $fwdir = scorm_get_preorder($constrained);
 536  
 537              if (array_search($fwdir, $sco) !== false) {
 538                  $traverse = 'forward';
 539              } else {
 540                  $traverse = 'backward';
 541              }
 542              $seq = scorm_seq_choice_flow($constrained, $traverse, $seq);
 543              $actconsider = $seq->identifiedactivity;
 544              $avdescendents = Array();
 545              $avdescendents = scorm_get_available_descendents($actconsider);
 546              if (array_search ($avdescendents, $sco) !== false && $sco->id != $actconsider->id && $constrained->id != $sco->id ) {
 547                  $seq->delivery = null;
 548                  $seq->exception = 'SB.2.9-8';
 549                  return $seq;
 550              }
 551              // CONTINUE 11.5.5 !
 552          }
 553  
 554          $commonpos = scorm_find_common_ancestor($ancestors, $seq->currentactivity);
 555          $comtarget = array_slice($ancestors, 1, $commonpos - 1);// Path from the common ancestor to the target activity.
 556          $comtarget = array_reverse($comtarget);
 557  
 558          if (empty($comtarget)) {
 559              $seq->delivery = null;
 560              $seq->exception = 'SB.2.9-5';
 561              return $seq;
 562          }
 563  
 564          $fwdir = scorm_get_preorder($seq->currentactivity);
 565  
 566          if (array_search($fwdir, $sco) !== false) {
 567              foreach ($comtarget as $act) {
 568                  $seq = scorm_seq_choice_activity_traversal($act, $userid, $seq, 'forward');
 569                  if (!$seq->reachable) {
 570                      $seq->delivery = null;
 571                      return $seq;
 572                  }
 573                  $act = scorm_get_sco($act->id);
 574                  if (scorm_seq_is('active', $act->id, $userid) && ($act->id != $comancestor->id &&
 575                          ($act->preventactivation == true))) {
 576                      $seq->delivery = null;
 577                      $seq->exception = 'SB.2.9-6';
 578                      return $seq;
 579                  }
 580              }
 581  
 582          } else {
 583              foreach ($comtarget as $act) {
 584                  $act = scorm_get_sco($act->id);
 585                  if (scorm_seq_is('active', $act->id, $userid) && $act->id != $comancestor->id && $act->preventactivation == true) {
 586                      $seq->delivery = null;
 587                      $seq->exception = 'SB.2.9-6';
 588                      return $seq;
 589                  }
 590              }
 591          }
 592          break;
 593      }
 594  
 595      if (scorm_is_leaf ($sco)) {
 596          $seq->delivery = $sco;
 597          $seq->exception = 'SB.2.9-6';
 598          return $seq;
 599      }
 600  
 601      $seq = scorm_seq_flow($sco, 'forward', $seq, true, $userid);
 602      if ($seq->deliverable == false) {
 603          scorm_terminate_descendent_attempts($comancestor, $userid, $seq);
 604          scorm_seq_end_attempt($comancestor, $userid, $seq->attempt);
 605          $seq->currentactivity = $sco;
 606          $seq->delivery = null;
 607          $seq->exception = 'SB.2.9-9';
 608          return $seq;
 609      } else {
 610          return $seq;
 611      }
 612  
 613  }
 614  
 615  function scorm_seq_choice_flow ($constrained, $traverse, $seq) {
 616      $seq = scorm_seq_choice_flow_tree ($constrained, $traverse, $seq);
 617      if ($seq->identifiedactivity == null) {
 618          $seq->identifiedactivity = $constrained;
 619          return $seq;
 620      } else {
 621          return $seq;
 622      }
 623  }
 624  
 625  function scorm_seq_choice_flow_tree ($constrained, $traverse, $seq) {
 626      $islast = false;
 627      $parent = scorm_get_parent ($constrained);
 628      if ($traverse == 'forward') {
 629          $preord = scorm_get_preorder($constrained);
 630          if (count($preorder) == 0 || (count($preorder) == 0 && $preorder[0]->id = $constrained->id)) {
 631              // TODO: undefined.
 632              $islast = true; // The function is the last activity available.
 633          }
 634          if ($constrained->parent == '/' || $islast) {
 635              $seq->nextactivity = null;
 636              return $seq;
 637          }
 638          $avchildren = scorm_get_available_children($parent); // Available children.
 639          if ($avchildren[count($avchildren) - 1]->id == $constrained->id) {
 640              $seq = scorm_seq_choice_flow_tree ($parent, 'forward', $seq);
 641              return $seq;
 642          } else {
 643              $i = 0;
 644              while ($i < count($avchildren)) {
 645                  if ($avchildren [$i]->id == $constrained->id) {
 646                      $seq->nextactivity = $avchildren [$i + 1];
 647                      return $seq;
 648                  } else {
 649                      $i++;
 650                  }
 651              }
 652          }
 653      }
 654  
 655      if ($traverse == 'backward') {
 656          if ($constrained->parent == '/' ) {
 657              $seq->nextactivity = null;
 658              return $seq;
 659          }
 660  
 661          $avchildren = scorm_get_available_children($parent); // Available children.
 662          if ($avchildren [0]->id == $constrained->id) {
 663              $seq = scorm_seq_choice_flow_tree ($parent, 'backward', $seq);
 664              return $seq;
 665          } else {
 666              $i = count($avchildren) - 1;
 667              while ($i >= 0) {
 668                  if ($avchildren [$i]->id == $constrained->id) {
 669                      $seq->nextactivity = $avchildren [$i - 1];
 670                      return $seq;
 671                  } else {
 672                      $i--;
 673                  }
 674              }
 675          }
 676      }
 677  }
 678  
 679  function scorm_seq_choice_activity_traversal($activity, $userid, $seq, $direction) {
 680      if ($direction == 'forward') {
 681          $act = scorm_seq_rules_check($activity, 'stopforwardtraversal');
 682  
 683          if ($act != null) {
 684              $seq->reachable = false;
 685              $seq->exception = 'SB.2.4-1';
 686              return $seq;
 687          }
 688          $seq->reachable = false;
 689          return $seq;
 690      }
 691  
 692      if ($direction == 'backward') {
 693          $parentsco = scorm_get_parent($activity);
 694          if ($parentsco != null) {
 695              if (isset($parentsco->forwardonly) && ($parentsco->forwardonly == true)) {
 696                  $seq->reachable = false;
 697                  $seq->exception = 'SB.2.4-2';
 698                  return $seq;
 699              } else {
 700                  $seq->reachable = false;
 701                  $seq->exception = 'SB.2.4-3';
 702                  return $seq;
 703              }
 704          }
 705      }
 706      $seq->reachable = true;
 707      return $seq;
 708  }
 709  
 710  // Delivery Request Process.
 711  
 712  function scorm_sequencing_delivery($scoid, $userid, $seq) {
 713  
 714      if (!scorm_is_leaf($seq->delivery)) {
 715          $seq->deliveryvalid = false;
 716          $seq->exception = 'DB.1.1-1';
 717          return $seq;
 718      }
 719      $ancestors = scorm_get_ancestors($seq->delivery);
 720      $arrpath = array_reverse($ancestors);
 721      array_push ($arrpath, $seq->delivery); // Path from the root to the target.
 722  
 723      if (empty($arrpath)) {
 724          $seq->deliveryvalid = false;
 725          $seq->exception = 'DB.1.1-2';
 726          return $seq;
 727      }
 728  
 729      foreach ($arrpath as $activity) {
 730          if (scorm_check_activity($activity, $userid)) {
 731              $seq->deliveryvalid = false;
 732              $seq->exception = 'DB.1.1-3';
 733              return $seq;
 734          }
 735      }
 736  
 737      $seq->deliveryvalid = true;
 738      return $seq;
 739  
 740  }
 741  
 742  function scorm_content_delivery_environment($seq, $userid) {
 743      global $DB;
 744  
 745      $act = $seq->currentactivity;
 746      if (scorm_seq_is('active', $act->id, $userid)) {
 747          $seq->exception = 'DB.2-1';
 748          return $seq;
 749      }
 750      $track = $DB->get_record('scorm_scoes_track', array('scoid' => $act->id,
 751                                                          'userid' => $userid,
 752                                                          'element' => 'suspendedactivity'));
 753      if ($track != null) {
 754          $seq = scorm_clear_suspended_activity($seq->delivery, $seq, $userid);
 755  
 756      }
 757      $seq = scorm_terminate_descendent_attempts ($seq->delivery, $userid, $seq);
 758      $ancestors = scorm_get_ancestors($seq->delivery);
 759      $arrpath = array_reverse($ancestors);
 760      array_push ($arrpath, $seq->delivery);
 761      foreach ($arrpath as $activity) {
 762          if (!scorm_seq_is('active', $activity->id, $userid)) {
 763              if (!isset($activity->tracked) || ($activity->tracked == 1)) {
 764                  if (!scorm_seq_is('suspended', $activity->id, $userid)) {
 765                      $r = $DB->get_record('scorm_scoes_track', array('scoid' => $activity->id,
 766                                                                      'userid' => $userid,
 767                                                                      'element' => 'activityattemptcount'));
 768                      $r->value = ($r->value) + 1;
 769                      $DB->update_record('scorm_scoes_track', $r);
 770                      if ($r->value == 1) {
 771                          scorm_seq_set('activityprogressstatus', $activity->id, $userid, 'true');
 772                      }
 773                      scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectiveprogressstatus', 'false');
 774                      scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectivesatisfiedstatus', 'false');
 775                      scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectivemeasurestatus', 'false');
 776                      scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectivenormalizedmeasure', 0.0);
 777  
 778                      scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptprogressstatus', 'false');
 779                      scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptcompletionstatus', 'false');
 780                      scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptabsoluteduration', 0.0);
 781                      scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptexperiencedduration', 0.0);
 782                      scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptcompletionamount', 0.0);
 783                  }
 784              }
 785              scorm_seq_set('active', $activity->id, $userid, 'true');
 786          }
 787      }
 788      $seq->delivery = $seq->currentactivity;
 789      scorm_seq_set('suspendedactivity', $activity->id, $userid, 'false');
 790  
 791      // ONCE THE DELIVERY BEGINS (How should I check that?).
 792  
 793      if (isset($activity->tracked) || ($activity->tracked == 0)) {
 794          // How should I track the info and what should I do to not record the information for the activity during delivery?
 795          $atabsdur = $DB->get_record('scorm_scoes_track', array('scoid' => $activity->id,
 796                                                                  'userid' => $userid,
 797                                                                  'element' => 'attemptabsoluteduration'));
 798          $atexpdur = $DB->get_record('scorm_scoes_track', array('scoid' => $activity->id,
 799                                                                  'userid' => $userid,
 800                                                                  'element' => 'attemptexperiencedduration'));
 801      }
 802      return $seq;
 803  }
 804  
 805  function scorm_clear_suspended_activity($act, $seq, $userid) {
 806      global $DB;
 807      $currentact = $seq->currentactivity;
 808      $track = $DB->get_record('scorm_scoes_track', array('scoid' => $currentact->id,
 809                                                          'userid' => $userid,
 810                                                          'element' => 'suspendedactivity'));
 811      if ($track != null) {
 812          $ancestors = scorm_get_ancestors($act);
 813          $commonpos = scorm_find_common_ancestor($ancestors, $currentact);
 814          if ($commonpos !== false) {
 815              if ($activitypath = array_slice($ancestors, 0, $commonpos)) {
 816                  if (!empty($activitypath)) {
 817  
 818                      foreach ($activitypath as $activity) {
 819                          if (scorm_is_leaf($activity)) {
 820                              scorm_seq_set('suspended', $activity->id, $userid, false);
 821                          } else {
 822                              $children = scorm_get_children($activity);
 823                              $bool = false;
 824                              foreach ($children as $child) {
 825                                  if (scorm_seq_is('suspended', $child->id, $userid)) {
 826                                      $bool = true;
 827                                  }
 828                              }
 829                              if (!$bool) {
 830                                  scorm_seq_set('suspended', $activity->id, $userid, false);
 831                              }
 832                          }
 833                      }
 834                  }
 835              }
 836          }
 837          scorm_seq_set('suspendedactivity', $act->id, $userid, false);
 838      }
 839  }
 840  
 841  function scorm_select_children_process($scoid, $userid) {
 842      global $DB;
 843  
 844      $sco = scorm_get_sco($scoid);
 845      if (!scorm_is_leaf($sco)) {
 846          if (!scorm_seq_is('suspended', $scoid, $userid) && !scorm_seq_is('active', $scoid, $userid)) {
 847              $r = $DB->get_record('scorm_scoes_track', array('scoid' => $scoid,
 848                                                              'userid' => $userid,
 849                                                              'element' => 'selectiontiming'));
 850  
 851              switch ($r->value) {
 852                  case 'oneachnewattempt':
 853                  case 'never':
 854                  break;
 855  
 856                  case 'once':
 857                      if (!scorm_seq_is('activityprogressstatus', $scoid, $userid)) {
 858                          if (scorm_seq_is('selectioncountsstatus', $scoid, $userid)) {
 859                              $childlist = '';
 860                              $res = $DB->get_record('scorm_scoes_track', array('scoid' => $scoid,
 861                                                                                  'userid' => $userid,
 862                                                                                  'element' => 'selectioncount'));
 863                              $i = ($res->value) - 1;
 864                              $children = scorm_get_children($sco);
 865  
 866                              while ($i >= 0) {
 867                                  $pos = array_rand($children);
 868                                  array_push($childlist, $children[$pos]);
 869                                  array_splice($children, $pos, 1);
 870                                  $i--;
 871                              }
 872                              sort($childlist);
 873                              $clist = serialize($childlist);
 874                              scorm_seq_set('availablechildren', $scoid, $userid, false);
 875                              scorm_seq_set('availablechildren', $scoid, $userid, $clist);
 876                          }
 877                      }
 878                  break;
 879              }
 880          }
 881      }
 882  }
 883  
 884  function scorm_randomize_children_process($scoid, $userid) {
 885      global $DB;
 886  
 887      $sco = scorm_get_sco($scoid);
 888      if (!scorm_is_leaf($sco)) {
 889          if (!scorm_seq_is('suspended', $scoid, $userid) && !scorm_seq_is('active', $scoid, $userid)) {
 890              $r = $DB->get_record('scorm_scoes_track', array('scoid' => $scoid,
 891                                                              'userid' => $userid,
 892                                                              'element' => 'randomizationtiming'));
 893  
 894              switch ($r->value) {
 895                  case 'never':
 896                  break;
 897  
 898                  case 'oneachnewattempt':
 899                  case 'once':
 900                      if (!scorm_seq_is('activityprogressstatus', $scoid, $userid)) {
 901                          if (scorm_seq_is('randomizechildren', $scoid, $userid)) {
 902                              $childlist = array();
 903                              $res = scorm_get_available_children($sco);
 904                              $i = count($res) - 1;
 905                              $children = $res->value;
 906  
 907                              while ($i >= 0) {
 908                                  $pos = array_rand($children);
 909                                  array_push($childlist, $children[$pos]);
 910                                  array_splice($children, $pos, 1);
 911                                  $i--;
 912                              }
 913  
 914                              $clist = serialize ($childlist);
 915                              scorm_seq_set('availablechildren', $scoid, $userid, false);
 916                              scorm_seq_set('availablechildren', $scoid, $userid, $clist);
 917                          }
 918                      }
 919                  break;
 920              }
 921          }
 922      }
 923  }
 924  
 925  function scorm_terminate_descendent_attempts($activity, $userid, $seq) {
 926      $ancestors = scorm_get_ancestors($seq->currentactivity);
 927      $commonpos = scorm_find_common_ancestor($ancestors, $activity);
 928      if ($commonpos !== false) {
 929          if ($activitypath = array_slice($ancestors, 1, $commonpos - 2)) {
 930              if (!empty($activitypath)) {
 931                  foreach ($activitypath as $sco) {
 932                      scorm_seq_end_attempt($sco, $userid, $seq->attempt);
 933                  }
 934              }
 935          }
 936      }
 937  }
 938  
 939  function scorm_sequencing_exception($seq) {
 940      global $OUTPUT;
 941      if ($seq->exception != null) {
 942          switch ($seq->exception) {
 943              case 'NB.2.1-1':
 944                  echo $OUTPUT->notification("Sequencing session has already begun");
 945              break;
 946              case 'NB.2.1-2':
 947                  echo $OUTPUT->notification("Sequencing session has not begun");
 948              break;
 949              case 'NB.2.1-3':
 950                  echo $OUTPUT->notification("Suspended activity is not defined");
 951              break;
 952              case 'NB.2.1-4':
 953                  echo $OUTPUT->notification("Flow Sequencing Control Model Violation");
 954              break;
 955              case 'NB.2.1-5':
 956                  echo $OUTPUT->notification("Flow or Forward only Sequencing Control Model Violation");
 957              break;
 958              case 'NB.2.1-6':
 959                  echo $OUTPUT->notification("No activity is previous to the root");
 960              break;
 961              case 'NB.2.1-7':
 962                  echo $OUTPUT->notification("Unsupported Navigation Request");
 963              break;
 964              case 'NB.2.1-8':
 965                  echo $OUTPUT->notification("Choice Exit Sequencing Control Model Violation");
 966              break;
 967              case 'NB.2.1-9':
 968                  echo $OUTPUT->notification("No activities to consider");
 969              break;
 970              case 'NB.2.1-10':
 971                  echo $OUTPUT->notification("Choice Sequencing Control Model Violation");
 972              break;
 973              case 'NB.2.1-11':
 974                  echo $OUTPUT->notification("Target Activity does not exist");
 975              break;
 976              case 'NB.2.1-12':
 977                  echo $OUTPUT->notification("Current Activity already terminated");
 978              break;
 979              case 'NB.2.1-13':
 980                  echo $OUTPUT->notification("Undefined Navigation Request");
 981              break;
 982  
 983              case 'TB.2.3-1':
 984                  echo $OUTPUT->notification("Current Activity already terminated");
 985              break;
 986              case 'TB.2.3-2':
 987                  echo $OUTPUT->notification("Current Activity already terminated");
 988              break;
 989              case 'TB.2.3-4':
 990                  echo $OUTPUT->notification("Current Activity already terminated");
 991              break;
 992              case 'TB.2.3-5':
 993                  echo $OUTPUT->notification("Nothing to suspend; No active activities");
 994              break;
 995              case 'TB.2.3-6':
 996                  echo $OUTPUT->notification("Nothing to abandon; No active activities");
 997              break;
 998  
 999              case 'SB.2.1-1':
1000                  echo $OUTPUT->notification("Last activity in the tree");
1001              break;
1002              case 'SB.2.1-2':
1003                  echo $OUTPUT->notification("Cluster has no available children");
1004              break;
1005              case 'SB.2.1-3':
1006                  echo $OUTPUT->notification("No activity is previous to the root");
1007              break;
1008              case 'SB.2.1-4':
1009                  echo $OUTPUT->notification("Forward Only Sequencing Control Model Violation");
1010              break;
1011  
1012              case 'SB.2.2-1':
1013                  echo $OUTPUT->notification("Flow Sequencing Control Model Violation");
1014              break;
1015              case 'SB.2.2-2':
1016                  echo $OUTPUT->notification("Activity unavailable");
1017              break;
1018  
1019              case 'SB.2.3-1':
1020                  echo $OUTPUT->notification("Forward Traversal Blocked");
1021              break;
1022              case 'SB.2.3-2':
1023                  echo $OUTPUT->notification("Forward Only Sequencing Control Model Violation");
1024              break;
1025              case 'SB.2.3-3':
1026                  echo $OUTPUT->notification("No activity is previous to the root");
1027              break;
1028  
1029              case 'SB.2.5-1':
1030                  echo $OUTPUT->notification("Sequencing session has already begun");
1031              break;
1032  
1033              case 'SB.2.6-1':
1034                  echo $OUTPUT->notification("Sequencing session has already begun");
1035              break;
1036              case 'SB.2.6-2':
1037                  echo $OUTPUT->notification("No Suspended activity is defined");
1038              break;
1039  
1040              case 'SB.2.7-1':
1041                  echo $OUTPUT->notification("Sequencing session has not begun");
1042              break;
1043              case 'SB.2.7-2':
1044                  echo $OUTPUT->notification("Flow Sequencing Control Model Violation");
1045              break;
1046  
1047              case 'SB.2.8-1':
1048                  echo $OUTPUT->notification("Sequencing session has not begun");
1049              break;
1050              case 'SB.2.8-2':
1051                  echo $OUTPUT->notification("Flow Sequencing Control Model Violation");
1052              break;
1053  
1054              case 'SB.2.9-1':
1055                  echo $OUTPUT->notification("No target for Choice");
1056              break;
1057              case 'SB.2.9-2':
1058                  echo $OUTPUT->notification("Target Activity does not exist or is unavailable");
1059              break;
1060              case 'SB.2.9-3':
1061                  echo $OUTPUT->notification("Target Activity hidden from choice");
1062              break;
1063              case 'SB.2.9-4':
1064                  echo $OUTPUT->notification("Choice Sequencing Control Model Violation");
1065              break;
1066              case 'SB.2.9-5':
1067                  echo $OUTPUT->notification("No activities to consider");
1068              break;
1069              case 'SB.2.9-6':
1070                  echo $OUTPUT->notification("Unable to activate target; target is not a child of the Current Activity");
1071              break;
1072              case 'SB.2.9-7':
1073                  echo $OUTPUT->notification("Choice Exit Sequencing Control Model Violation");
1074              break;
1075              case 'SB.2.9-8':
1076                  echo $OUTPUT->notification("Unable to choose target activity - constrained choice");
1077              break;
1078              case 'SB.2.9-9':
1079                  echo $OUTPUT->notification("Choice Request Prevented by Flow-only Activity");
1080              break;
1081  
1082              case 'SB.2.10-1':
1083                  echo $OUTPUT->notification("Sequencing session has not begun");
1084              break;
1085              case 'SB.2.10-2':
1086                  echo $OUTPUT->notification("Current Activity is active or suspended");
1087              break;
1088              case 'SB.2.10-3':
1089                  echo $OUTPUT->notification("Flow Sequencing Control Model Violation");
1090              break;
1091  
1092              case 'SB.2.11-1':
1093                  echo $OUTPUT->notification("Sequencing session has not begun");
1094              break;
1095              case 'SB.2.11-2':
1096                  echo $OUTPUT->notification("Current Activity has not been terminated");
1097              break;
1098  
1099              case 'SB.2.12-2':
1100                  echo $OUTPUT->notification("Undefined Sequencing Request");
1101              break;
1102  
1103              case 'DB.1.1-1':
1104                  echo $OUTPUT->notification("Cannot deliver a non-leaf activity");
1105              break;
1106              case 'DB.1.1-2':
1107                  echo $OUTPUT->notification("Nothing to deliver");
1108              break;
1109              case 'DB.1.1-3':
1110                  echo $OUTPUT->notification("Activity unavailable");
1111              break;
1112  
1113              case 'DB.2-1':
1114                  echo $OUTPUT->notification("Identified activity is already active");
1115              break;
1116  
1117          }
1118  
1119      }
1120  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1