AutorÃa | Ultima modificación | Ver Log |
<?php// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>.function scorm_seq_exit_action_rules($seq, $userid) {$sco = $seq->currentactivity;$ancestors = scorm_get_ancestors($sco);$exittarget = null;foreach (array_reverse($ancestors) as $ancestor) {if (scorm_seq_rules_check($ancestor, 'exit') != null) {$exittarget = $ancestor;break;}}if ($exittarget != null) {$commons = array_slice($ancestors, 0, scorm_find_common_ancestor($ancestors, $exittarget));// Terminate Descendent Attempts Process.if ($commons) {foreach ($commons as $ancestor) {scorm_seq_end_attempt($ancestor, $userid, $seq->attempt);$seq->currentactivity = $ancestor;}}}return $seq;}function scorm_seq_post_cond_rules($seq, $userid) {$sco = $seq->currentactivity;if (!$seq->suspended) {if ($action = scorm_seq_rules_check($sco, 'post') != null) {switch($action) {case 'retry':case 'continue':case 'previous':$seq->sequencing = $action;break;case 'exitparent':case 'exitall':$seq->termination = $action;break;case 'retryall':$seq->termination = 'exitall';$seq->sequencing = 'retry';break;}}}return $seq;}function scorm_seq_evaluate_rollupcond($sco, $conditioncombination, $rollupruleconds, $userid) {$bag = Array();$con = "";$val = false;$unk = false;foreach ($rollupruleconds as $rolluprulecond) {$condit = scorm_evaluate_condition($rolluprulecond, $sco, $userid);if ($rolluprulecond->operator == 'not') { // If operator is not, negate the condition.if ($rolluprulecond->cond != 'unknown') {if ($condit) {$condit = false;} else {$condit = true;}} else {$condit = 'unknown';}array_push($childrenbag, $condit);}}if (empty($bag)) {return 'unknown';} else {$i = 0;foreach ($bag as $b) {if ($rolluprulecond->conditioncombination == 'all') {$val = true;if ($b == 'unknown') {$unk = true;}if ($b === false) {return false;}} else {$val = false;if ($b == 'unknown') {$unk = true;}if ($b === true) {return true;}}}}if ($unk) {return 'unknown';}return $val;}function scorm_seq_check_child ($sco, $action, $userid) {global $DB;$included = false;$sco = scorm_get_sco($sco->id);$r = scorm_get_sco_value($sco->id, $userid, 'activityattemptcount');if ($action == 'satisfied' || $action == 'notsatisfied') {if (!$sco->rollupobjectivesatisfied) {$included = true;if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifnotsuspended') ||($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifnotsuspended')) {if (!scorm_seq_is('activityprogressstatus', $sco->id, $userid) ||((($r->value) > 0) && !scorm_seq_is('suspended', $sco->id, $userid))) {$included = false;}} else {if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifattempted') ||($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifattempted')) {if (!scorm_seq_is('activityprogressstatus', $sco->id, $userid) || (($r->value) == 0)) {$included = false;}} else {if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifnotskipped') ||($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifnotskipped')) {$rulch = scorm_seq_rules_check($sco, 'skip');if ($rulch != null) {$included = false;}}}}}}if ($action == 'completed' || $action == 'incomplete') {if (!$sco->rollupprogresscompletion) {$included = true;if (($action == 'completed' && $sco->requiredforcompleted == 'ifnotsuspended') ||($action == 'incomplete' && $sco->requiredforincomplete == 'ifnotsuspended')) {if (!scorm_seq_is('activityprogressstatus', $sco->id, $userid) ||((($r->value) > 0)&& !scorm_seq_is('suspended', $sco->id, $userid))) {$included = false;}} else {if (($action == 'completed' && $sco->requiredforcompleted == 'ifattempted') ||($action == 'incomplete' && $sco->requiredforincomplete == 'ifattempted')) {if (!scorm_seq_is('activityprogressstatus', $sco->id, $userid) || (($r->value) == 0)) {$included = false;}} else {if (($action == 'completed' && $sco->requiredforsatisfied == 'ifnotskipped') ||($action == 'incomplete' && $sco->requiredfornotsatisfied == 'ifnotskipped')) {$rulch = scorm_seq_rules_check($sco, 'skip');if ($rulch != null) {$included = false;}}}}}}return $included;}function scorm_seq_sequencing ($scoid, $userid, $seq) {switch ($seq->sequencing) {case 'start':// We'll see the parameters we have to send, this should update delivery and end.$seq = scorm_seq_start_sequencing($scoid, $userid, $seq);$seq->sequencing = true;break;case 'resumeall':// We'll see the parameters we have to send, this should update delivery and end.$seq = scorm_seq_resume_all_sequencing($scoid, $userid, $seq);$seq->sequencing = true;break;case 'exit':// We'll see the parameters we have to send, this should update delivery and end.$seq = scorm_seq_exit_sequencing($scoid, $userid, $seq);$seq->sequencing = true;break;case 'retry':// We'll see the parameters we have to send, this should update delivery and end.$seq = scorm_seq_retry_sequencing($scoid, $userid, $seq);$seq->sequencing = true;break;case 'previous':// We'll see the parameters we have to send, this should update delivery and end.$seq = scorm_seq_previous_sequencing($scoid, $userid, $seq);$seq->sequencing = true;break;case 'choice':// We'll see the parameters we have to send, this should update delivery and end.$seq = scorm_seq_choice_sequencing($scoid, $userid, $seq);$seq->sequencing = true;break;}if ($seq->exception != null) {$seq->sequencing = false;return $seq;}$seq->sequencing = true;return $seq;}function scorm_seq_start_sequencing($scoid, $userid, $seq) {global $DB;if (!empty($seq->currentactivity)) {$seq->delivery = null;$seq->exception = 'SB.2.5-1';return $seq;}$sco = $DB->get_record('scorm_scoes', array('scoid' => $scoid, 'userid' => $userid));if (($sco->parent == '/') && scorm_is_leaf($sco)) { // If the activity is the root and is leaf.$seq->delivery = $sco;} else {$ancestors = scorm_get_ancestors($sco);$ancestorsroot = array_reverse($ancestors);$res = scorm_seq_flow($ancestorsroot[0], 'forward', $seq, true, $userid);if ($res) {return $res;}}}function scorm_seq_resume_all_sequencing($scoid, $userid, $seq) {global $DB;if (!empty($seq->currentactivity)) {$seq->delivery = null;$seq->exception = 'SB.2.6-1';return $seq;}$track = scorm_get_sco_value($scoid, $userid, 'suspendedactivity');if (!$track) {$seq->delivery = null;$seq->exception = 'SB.2.6-2';return $seq;}// We assign the sco to the delivery.$seq->delivery = $DB->get_record('scorm_scoes', array('scoid' => $scoid, 'userid' => $userid));}function scorm_seq_continue_sequencing($scoid, $userid, $seq) {if (empty($seq->currentactivity)) {$seq->delivery = null;$seq->exception = 'SB.2.7-1';return $seq;}$currentact = $seq->currentactivity;if ($currentact->parent != '/') {// If the activity is the root and is leaf.$parent = scorm_get_parent ($currentact);if (!isset($parent->flow) || ($parent->flow == false)) {$seq->delivery = null;$seq->exception = 'SB.2.7-2';return $seq;}$res = scorm_seq_flow($currentact, 'forward', $seq, false, $userid);if ($res) {return $res;}}}function scorm_seq_previous_sequencing($scoid, $userid, $seq) {if (empty($seq->currentactivity)) {$seq->delivery = null;$seq->exception = 'SB.2.8-1';return $seq;}$currentact = $seq->currentactivity;if ($currentact->parent != '/') { // If the activity is the root and is leaf.$parent = scorm_get_parent ($currentact);if (!isset($parent->flow) || ($parent->flow == false)) {$seq->delivery = null;$seq->exception = 'SB.2.8-2';return $seq;}$res = scorm_seq_flow($currentact, 'backward', $seq, false, $userid);if ($res) {return $res;}}}function scorm_seq_exit_sequencing($scoid, $userid, $seq) {if (empty($seq->currentactivity)) {$seq->delivery = null;$seq->exception = 'SB.2.11-1';return $seq;}if ($seq->active) {$seq->endsession = false;$seq->exception = 'SB.2.11-2';return $seq;}$currentact = $seq->currentactivity;if ($currentact->parent == '/') {$seq->endsession = true;return $seq;}$seq->endsession = false;return $seq;}function scorm_seq_retry_sequencing($scoid, $userid, $seq) {if (empty($seq->currentactivity)) {$seq->delivery = null;$seq->exception = 'SB.2.10-1';return $seq;}if ($seq->active || $seq->suspended) {$seq->delivery = null;$seq->exception = 'SB.2.10-2';return $seq;}if (!scorm_is_leaf($seq->currentactivity)) {$res = scorm_seq_flow($seq->currentactivity, 'forward', $seq, true, $userid);if ($res != null) {return $res;} else {// Return deliver.$seq->delivery = null;$seq->exception = 'SB.2.10-3';return $seq;}} else {$seq->delivery = $seq->currentactivity;return $seq;}}function scorm_seq_choice_sequencing($sco, $userid, $seq) {$avchildren = Array ();$comancestor = null;$traverse = null;if ($sco == null) {$seq->delivery = null;$seq->exception = 'SB.2.9-1';return $seq;}$ancestors = scorm_get_ancestors($sco);$arrpath = array_reverse($ancestors);array_push ($arrpath, $sco); // Path from the root to the target.foreach ($arrpath as $activity) {if ($activity->parent != '/') {$avchildren = scorm_get_available_children (scorm_get_parent($activity));$position = array_search($avchildren, $activity);if ($position !== false) {$seq->delivery = null;$seq->exception = 'SB.2.9-2';return $seq;}}if (scorm_seq_rules_check($activity, 'hidefromchoice' != null)) {$seq->delivery = null;$seq->exception = 'SB.2.9-3';return $seq;}}if ($sco->parent != '/') {$parent = scorm_sco_get_parent ($sco);if ( isset($parent->choice) && ($parent->choice == false)) {$seq->delivery = null;$seq->exception = 'SB.2.9-4';return $seq;}}if ($seq->currentactivity != null) {$commonpos = scorm_find_common_ancestor($ancestors, $seq->currentactivity);$comancestor = $arrpath [$commonpos];} else {$comancestor = $arrpath [0];}if ($seq->currentactivity === $sco) {// MDL-51757 - this part of the SCORM 2004 sequencing and navigation was not completed.throw new \coding_exception('Unexpected state encountered');}$sib = scorm_get_siblings($seq->currentactivity);$pos = array_search($sib, $sco);if ($pos !== false) {$siblings = array_slice($sib, 0, $pos - 1);if (empty($siblings)) {$seq->delivery = null;$seq->exception = 'SB.2.9-5';return $seq;}$children = scorm_get_children (scorm_get_parent ($sco));$pos1 = array_search($children, $sco);$pos2 = array_search($seq->currentactivity, $sco);if ($pos1 > $pos2) {$traverse = 'forward';} else {$traverse = 'backward';}foreach ($siblings as $sibling) {$seq = scorm_seq_choice_activity_traversal($sibling, $userid, $seq, $traverse);if (!$seq->reachable) {$seq->delivery = null;return $seq;}}// MDL-51757 - this part of the SCORM 2004 sequencing and navigation was not completed.throw new \coding_exception('Unexpected state encountered');}if ($seq->currentactivity == null || $seq->currentactivity == $comancestor) {$commonpos = scorm_find_common_ancestor($ancestors, $seq->currentactivity);// Path from the common ancestor to the target activity.$comtarget = array_slice($ancestors, 1, $commonpos - 1);$comtarget = array_reverse($comtarget);if (empty($comtarget)) {$seq->delivery = null;$seq->exception = 'SB.2.9-5';return $seq;}foreach ($comtarget as $act) {$seq = scorm_seq_choice_activity_traversal($act, $userid, $seq, 'forward');if (!$seq->reachable) {$seq->delivery = null;return $seq;}$act = scorm_get_sco ($acti->id);if (scorm_seq_is('active', $act->id, $userid) && ($act->id != $comancestor->id && $act->preventactivation)) {$seq->delivery = null;$seq->exception = 'SB.2.9-6';return $seq;}}// MDL-51757 - this part of the SCORM 2004 sequencing and navigation was not completed.throw new \coding_exception('Unexpected state encountered');}if ($comancestor->id == $sco->id) {$ancestorscurrent = scorm_get_ancestors($seq->currentactivity);$possco = array_search($ancestorscurrent, $sco);// Path from the current activity to the target.$curtarget = array_slice($ancestorscurrent, 0, $possco);if (empty($curtarget)) {$seq->delivery = null;$seq->exception = 'SB.2.9-5';return $seq;}$i = 0;foreach ($curtarget as $activ) {$i++;if ($i != count($curtarget)) {if (isset($activ->choiceexit) && ($activ->choiceexit == false)) {$seq->delivery = null;$seq->exception = 'SB.2.9-7';return $seq;}}}// MDL-51757 - this part of the SCORM 2004 sequencing and navigation was not completed.throw new \coding_exception('Unexpected state encountered');}if (array_search($ancestors, $comancestor) !== false) {$ancestorscurrent = scorm_get_ancestors($seq->currentactivity);$commonpos = scorm_find_common_ancestor($ancestors, $sco);$curcommon = array_slice($ancestorscurrent, 0, $commonpos - 1);if (empty($curcommon)) {$seq->delivery = null;$seq->exception = 'SB.2.9-5';return $seq;}$constrained = null;foreach ($curcommon as $acti) {$acti = scorm_get_sco($acti->id);if (isset($acti->choiceexit) && ($acti->choiceexit == false)) {$seq->delivery = null;$seq->exception = 'SB.2.9-7';return $seq;}if ($constrained == null) {if ($acti->constrainchoice == true) {$constrained = $acti;}}}if ($constrained != null) {$fwdir = scorm_get_preorder($constrained);if (array_search($fwdir, $sco) !== false) {$traverse = 'forward';} else {$traverse = 'backward';}$seq = scorm_seq_choice_flow($constrained, $traverse, $seq);$actconsider = $seq->identifiedactivity;$avdescendents = Array();$avdescendents = scorm_get_available_descendents($actconsider);if (array_search ($avdescendents, $sco) !== false && $sco->id != $actconsider->id && $constrained->id != $sco->id ) {$seq->delivery = null;$seq->exception = 'SB.2.9-8';return $seq;}// CONTINUE 11.5.5 !}$commonpos = scorm_find_common_ancestor($ancestors, $seq->currentactivity);$comtarget = array_slice($ancestors, 1, $commonpos - 1);// Path from the common ancestor to the target activity.$comtarget = array_reverse($comtarget);if (empty($comtarget)) {$seq->delivery = null;$seq->exception = 'SB.2.9-5';return $seq;}$fwdir = scorm_get_preorder($seq->currentactivity);if (array_search($fwdir, $sco) !== false) {foreach ($comtarget as $act) {$seq = scorm_seq_choice_activity_traversal($act, $userid, $seq, 'forward');if (!$seq->reachable) {$seq->delivery = null;return $seq;}$act = scorm_get_sco($act->id);if (scorm_seq_is('active', $act->id, $userid) && ($act->id != $comancestor->id &&($act->preventactivation == true))) {$seq->delivery = null;$seq->exception = 'SB.2.9-6';return $seq;}}} else {foreach ($comtarget as $act) {$act = scorm_get_sco($act->id);if (scorm_seq_is('active', $act->id, $userid) && $act->id != $comancestor->id && $act->preventactivation == true) {$seq->delivery = null;$seq->exception = 'SB.2.9-6';return $seq;}}}// MDL-51757 - this part of the SCORM 2004 sequencing and navigation was not completed.throw new \coding_exception('Unexpected state encountered');}if (scorm_is_leaf ($sco)) {$seq->delivery = $sco;$seq->exception = 'SB.2.9-6';return $seq;}$seq = scorm_seq_flow($sco, 'forward', $seq, true, $userid);if ($seq->deliverable == false) {scorm_terminate_descendent_attempts($comancestor, $userid, $seq);scorm_seq_end_attempt($comancestor, $userid, $seq->attempt);$seq->currentactivity = $sco;$seq->delivery = null;$seq->exception = 'SB.2.9-9';return $seq;} else {return $seq;}}function scorm_seq_choice_flow ($constrained, $traverse, $seq) {$seq = scorm_seq_choice_flow_tree ($constrained, $traverse, $seq);if ($seq->identifiedactivity == null) {$seq->identifiedactivity = $constrained;return $seq;} else {return $seq;}}function scorm_seq_choice_flow_tree ($constrained, $traverse, $seq) {$islast = false;$parent = scorm_get_parent ($constrained);if ($traverse == 'forward') {$preord = scorm_get_preorder($constrained);if (count($preorder) == 0 || (count($preorder) == 0 && $preorder[0]->id = $constrained->id)) {// TODO: undefined.$islast = true; // The function is the last activity available.}if ($constrained->parent == '/' || $islast) {$seq->nextactivity = null;return $seq;}$avchildren = scorm_get_available_children($parent); // Available children.if ($avchildren[count($avchildren) - 1]->id == $constrained->id) {$seq = scorm_seq_choice_flow_tree ($parent, 'forward', $seq);return $seq;} else {$i = 0;while ($i < count($avchildren)) {if ($avchildren [$i]->id == $constrained->id) {$seq->nextactivity = $avchildren [$i + 1];return $seq;} else {$i++;}}}}if ($traverse == 'backward') {if ($constrained->parent == '/' ) {$seq->nextactivity = null;return $seq;}$avchildren = scorm_get_available_children($parent); // Available children.if ($avchildren [0]->id == $constrained->id) {$seq = scorm_seq_choice_flow_tree ($parent, 'backward', $seq);return $seq;} else {$i = count($avchildren) - 1;while ($i >= 0) {if ($avchildren [$i]->id == $constrained->id) {$seq->nextactivity = $avchildren [$i - 1];return $seq;} else {$i--;}}}}}function scorm_seq_choice_activity_traversal($activity, $userid, $seq, $direction) {if ($direction == 'forward') {$act = scorm_seq_rules_check($activity, 'stopforwardtraversal');if ($act != null) {$seq->reachable = false;$seq->exception = 'SB.2.4-1';return $seq;}$seq->reachable = false;return $seq;}if ($direction == 'backward') {$parentsco = scorm_get_parent($activity);if ($parentsco != null) {if (isset($parentsco->forwardonly) && ($parentsco->forwardonly == true)) {$seq->reachable = false;$seq->exception = 'SB.2.4-2';return $seq;} else {$seq->reachable = false;$seq->exception = 'SB.2.4-3';return $seq;}}}$seq->reachable = true;return $seq;}// Delivery Request Process.function scorm_sequencing_delivery($scoid, $userid, $seq) {if (!scorm_is_leaf($seq->delivery)) {$seq->deliveryvalid = false;$seq->exception = 'DB.1.1-1';return $seq;}$ancestors = scorm_get_ancestors($seq->delivery);$arrpath = array_reverse($ancestors);array_push ($arrpath, $seq->delivery); // Path from the root to the target.if (empty($arrpath)) {$seq->deliveryvalid = false;$seq->exception = 'DB.1.1-2';return $seq;}foreach ($arrpath as $activity) {if (scorm_check_activity($activity, $userid)) {$seq->deliveryvalid = false;$seq->exception = 'DB.1.1-3';return $seq;}}$seq->deliveryvalid = true;return $seq;}function scorm_content_delivery_environment($seq, $userid) {global $DB;$act = $seq->currentactivity;if (scorm_seq_is('active', $act->id, $userid)) {$seq->exception = 'DB.2-1';return $seq;}$track = scorm_get_sco_value($act->id, $userid, 'suspendedactivity');if ($track != null) {$seq = scorm_clear_suspended_activity($seq->delivery, $seq, $userid);}$attemptobject = scorm_get_attempt($userid, $track->scormid, 0);$seq = scorm_terminate_descendent_attempts ($seq->delivery, $userid, $seq);$ancestors = scorm_get_ancestors($seq->delivery);$arrpath = array_reverse($ancestors);array_push ($arrpath, $seq->delivery);foreach ($arrpath as $activity) {if (!scorm_seq_is('active', $activity->id, $userid)) {if (!isset($activity->tracked) || ($activity->tracked == 1)) {if (!scorm_seq_is('suspended', $activity->id, $userid)) {$r = scorm_get_sco_value($activity->id, $userid, 'activityattemptcount');$value = new stdClass();$value->id = $r->valueid;$value->value = ($r->value) + 1;$DB->update_record('scorm_scoes_value', $value);if ($r->value == 1) {scorm_seq_set('activityprogressstatus', $activity->id, $userid, 'true');}scorm_insert_track($userid, $activity->scorm, $activity->id, $attemptobject,'objectiveprogressstatus', 'false');scorm_insert_track($userid, $activity->scorm, $activity->id, $attemptobject,'objectivesatisfiedstatus', 'false');scorm_insert_track($userid, $activity->scorm, $activity->id, $attemptobject,'objectivemeasurestatus', 'false');scorm_insert_track($userid, $activity->scorm, $activity->id, $attemptobject,'objectivenormalizedmeasure', 0.0);scorm_insert_track($userid, $activity->scorm, $activity->id, $attemptobject,'attemptprogressstatus', 'false');scorm_insert_track($userid, $activity->scorm, $activity->id, $attemptobject,'attemptcompletionstatus', 'false');scorm_insert_track($userid, $activity->scorm, $activity->id, $attemptobject,'attemptabsoluteduration', 0.0);scorm_insert_track($userid, $activity->scorm, $activity->id, $attemptobject,'attemptexperiencedduration', 0.0);scorm_insert_track($userid, $activity->scorm, $activity->id, $attemptobject,'attemptcompletionamount', 0.0);}}scorm_seq_set('active', $activity->id, $userid, 'true');}}$seq->delivery = $seq->currentactivity;scorm_seq_set('suspendedactivity', $activity->id, $userid, 'false');return $seq;}function scorm_clear_suspended_activity($act, $seq, $userid) {global $DB;$currentact = $seq->currentactivity;$track = scorm_get_sco_value($currentact->id, $userid, 'suspendedactivity');if ($track != null) {$ancestors = scorm_get_ancestors($act);$commonpos = scorm_find_common_ancestor($ancestors, $currentact);if ($commonpos !== false) {if ($activitypath = array_slice($ancestors, 0, $commonpos)) {if (!empty($activitypath)) {foreach ($activitypath as $activity) {if (scorm_is_leaf($activity)) {scorm_seq_set('suspended', $activity->id, $userid, false);} else {$children = scorm_get_children($activity);$bool = false;foreach ($children as $child) {if (scorm_seq_is('suspended', $child->id, $userid)) {$bool = true;}}if (!$bool) {scorm_seq_set('suspended', $activity->id, $userid, false);}}}}}}scorm_seq_set('suspendedactivity', $act->id, $userid, false);}}function scorm_select_children_process($scoid, $userid) {global $DB;$sco = scorm_get_sco($scoid);if (!scorm_is_leaf($sco)) {if (!scorm_seq_is('suspended', $scoid, $userid) && !scorm_seq_is('active', $scoid, $userid)) {$r = scorm_get_sco_value($scoid, $userid, 'selectiontiming');switch ($r->value) {case 'oneachnewattempt':case 'never':break;case 'once':if (!scorm_seq_is('activityprogressstatus', $scoid, $userid)) {if (scorm_seq_is('selectioncountsstatus', $scoid, $userid)) {$childlist = '';$res = scorm_get_sco_value($scoid, $userid, 'selectioncount');$i = ($res->value) - 1;$children = scorm_get_children($sco);while ($i >= 0) {$pos = array_rand($children);array_push($childlist, $children[$pos]);array_splice($children, $pos, 1);$i--;}sort($childlist);$clist = serialize($childlist);scorm_seq_set('availablechildren', $scoid, $userid, false);scorm_seq_set('availablechildren', $scoid, $userid, $clist);}}break;}}}}function scorm_randomize_children_process($scoid, $userid) {global $DB;$sco = scorm_get_sco($scoid);if (!scorm_is_leaf($sco)) {if (!scorm_seq_is('suspended', $scoid, $userid) && !scorm_seq_is('active', $scoid, $userid)) {$r = scorm_get_sco_value($scoid, $userid, 'randomizationtiming');switch ($r->value) {case 'never':break;case 'oneachnewattempt':case 'once':if (!scorm_seq_is('activityprogressstatus', $scoid, $userid)) {if (scorm_seq_is('randomizechildren', $scoid, $userid)) {$childlist = array();$res = scorm_get_available_children($sco);$i = count($res) - 1;$children = $res->value;while ($i >= 0) {$pos = array_rand($children);array_push($childlist, $children[$pos]);array_splice($children, $pos, 1);$i--;}$clist = serialize ($childlist);scorm_seq_set('availablechildren', $scoid, $userid, false);scorm_seq_set('availablechildren', $scoid, $userid, $clist);}}break;}}}}function scorm_terminate_descendent_attempts($activity, $userid, $seq) {$ancestors = scorm_get_ancestors($seq->currentactivity);$commonpos = scorm_find_common_ancestor($ancestors, $activity);if ($commonpos !== false) {if ($activitypath = array_slice($ancestors, 1, $commonpos - 2)) {if (!empty($activitypath)) {foreach ($activitypath as $sco) {scorm_seq_end_attempt($sco, $userid, $seq->attempt);}}}}}function scorm_sequencing_exception($seq) {global $OUTPUT;if ($seq->exception != null) {switch ($seq->exception) {case 'NB.2.1-1':echo $OUTPUT->notification("Sequencing session has already begun");break;case 'NB.2.1-2':echo $OUTPUT->notification("Sequencing session has not begun");break;case 'NB.2.1-3':echo $OUTPUT->notification("Suspended activity is not defined");break;case 'NB.2.1-4':echo $OUTPUT->notification("Flow Sequencing Control Model Violation");break;case 'NB.2.1-5':echo $OUTPUT->notification("Flow or Forward only Sequencing Control Model Violation");break;case 'NB.2.1-6':echo $OUTPUT->notification("No activity is previous to the root");break;case 'NB.2.1-7':echo $OUTPUT->notification("Unsupported Navigation Request");break;case 'NB.2.1-8':echo $OUTPUT->notification("Choice Exit Sequencing Control Model Violation");break;case 'NB.2.1-9':echo $OUTPUT->notification("No activities to consider");break;case 'NB.2.1-10':echo $OUTPUT->notification("Choice Sequencing Control Model Violation");break;case 'NB.2.1-11':echo $OUTPUT->notification("Target Activity does not exist");break;case 'NB.2.1-12':echo $OUTPUT->notification("Current Activity already terminated");break;case 'NB.2.1-13':echo $OUTPUT->notification("Undefined Navigation Request");break;case 'TB.2.3-1':echo $OUTPUT->notification("Current Activity already terminated");break;case 'TB.2.3-2':echo $OUTPUT->notification("Current Activity already terminated");break;case 'TB.2.3-4':echo $OUTPUT->notification("Current Activity already terminated");break;case 'TB.2.3-5':echo $OUTPUT->notification("Nothing to suspend; No active activities");break;case 'TB.2.3-6':echo $OUTPUT->notification("Nothing to abandon; No active activities");break;case 'SB.2.1-1':echo $OUTPUT->notification("Last activity in the tree");break;case 'SB.2.1-2':echo $OUTPUT->notification("Cluster has no available children");break;case 'SB.2.1-3':echo $OUTPUT->notification("No activity is previous to the root");break;case 'SB.2.1-4':echo $OUTPUT->notification("Forward Only Sequencing Control Model Violation");break;case 'SB.2.2-1':echo $OUTPUT->notification("Flow Sequencing Control Model Violation");break;case 'SB.2.2-2':echo $OUTPUT->notification("Activity unavailable");break;case 'SB.2.3-1':echo $OUTPUT->notification("Forward Traversal Blocked");break;case 'SB.2.3-2':echo $OUTPUT->notification("Forward Only Sequencing Control Model Violation");break;case 'SB.2.3-3':echo $OUTPUT->notification("No activity is previous to the root");break;case 'SB.2.5-1':echo $OUTPUT->notification("Sequencing session has already begun");break;case 'SB.2.6-1':echo $OUTPUT->notification("Sequencing session has already begun");break;case 'SB.2.6-2':echo $OUTPUT->notification("No Suspended activity is defined");break;case 'SB.2.7-1':echo $OUTPUT->notification("Sequencing session has not begun");break;case 'SB.2.7-2':echo $OUTPUT->notification("Flow Sequencing Control Model Violation");break;case 'SB.2.8-1':echo $OUTPUT->notification("Sequencing session has not begun");break;case 'SB.2.8-2':echo $OUTPUT->notification("Flow Sequencing Control Model Violation");break;case 'SB.2.9-1':echo $OUTPUT->notification("No target for Choice");break;case 'SB.2.9-2':echo $OUTPUT->notification("Target Activity does not exist or is unavailable");break;case 'SB.2.9-3':echo $OUTPUT->notification("Target Activity hidden from choice");break;case 'SB.2.9-4':echo $OUTPUT->notification("Choice Sequencing Control Model Violation");break;case 'SB.2.9-5':echo $OUTPUT->notification("No activities to consider");break;case 'SB.2.9-6':echo $OUTPUT->notification("Unable to activate target; target is not a child of the Current Activity");break;case 'SB.2.9-7':echo $OUTPUT->notification("Choice Exit Sequencing Control Model Violation");break;case 'SB.2.9-8':echo $OUTPUT->notification("Unable to choose target activity - constrained choice");break;case 'SB.2.9-9':echo $OUTPUT->notification("Choice Request Prevented by Flow-only Activity");break;case 'SB.2.10-1':echo $OUTPUT->notification("Sequencing session has not begun");break;case 'SB.2.10-2':echo $OUTPUT->notification("Current Activity is active or suspended");break;case 'SB.2.10-3':echo $OUTPUT->notification("Flow Sequencing Control Model Violation");break;case 'SB.2.11-1':echo $OUTPUT->notification("Sequencing session has not begun");break;case 'SB.2.11-2':echo $OUTPUT->notification("Current Activity has not been terminated");break;case 'SB.2.12-2':echo $OUTPUT->notification("Undefined Sequencing Request");break;case 'DB.1.1-1':echo $OUTPUT->notification("Cannot deliver a non-leaf activity");break;case 'DB.1.1-2':echo $OUTPUT->notification("Nothing to deliver");break;case 'DB.1.1-3':echo $OUTPUT->notification("Activity unavailable");break;case 'DB.2-1':echo $OUTPUT->notification("Identified activity is already active");break;}}}