|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00017 require ($CFG->dirroot.'/mod/scorm/datamodels/scormlib.php'); 00018 00019 function scorm_seq_evaluate($scoid,$usertracks) { 00020 return true; 00021 } 00022 00023 function scorm_seq_overall ($scoid,$userid,$request,$attempt) { 00024 $seq = scorm_seq_navigation($scoid,$userid,$request,$attempt); 00025 if ($seq->navigation) { 00026 if ($seq->termination != null) { 00027 $seq = scorm_seq_termination($scoid,$userid,$seq); 00028 } 00029 if ($seq->sequencing != null) { 00030 $seq = scorm_seq_sequencing($scoid,$userid,$seq); 00031 if($seq->sequencing == 'exit'){//return the control to the LTS 00032 return 'true'; 00033 } 00034 } 00035 if ($seq->delivery != null) { 00036 $seq = scorm_sequencing_delivery($scoid,$userid,$seq); 00037 $seq = scorm_content_delivery_environment ($seq,$userid); 00038 } 00039 } 00040 if ($seq->exception != null) { 00041 $seq = scorm_sequencing_exception($seq); 00042 } 00043 return 'true'; 00044 } 00045 00046 00047 function scorm_seq_navigation ($scoid,$userid,$request,$attempt=0) { 00048 global $DB; 00049 00051 $seq = new stdClass(); 00052 $seq->currentactivity = scorm_get_sco($scoid); 00053 $seq->traversaldir = null; 00054 $seq->nextactivity = null; 00055 $seq->deliveryvalid = null; 00056 $seq->attempt = $attempt; 00057 00058 $seq->identifiedactivity = null; 00059 $seq->delivery = null; 00060 $seq->deliverable = false; 00061 $seq->active = scorm_seq_is('active',$scoid,$userid); 00062 $seq->suspended = scorm_seq_is('suspended',$scoid,$userid); 00063 $seq->navigation = null; 00064 $seq->termination = null; 00065 $seq->sequencing = null; 00066 $seq->target = null; 00067 $seq->endsession = null; 00068 $seq->exception = null; 00069 $seq->reachable = true; 00070 $seq->prevact = true; 00071 00072 switch ($request) { 00073 case 'start_': 00074 if (empty($seq->currentactivity)) { 00075 $seq->navigation = true; 00076 $seq->sequencing = 'start'; 00077 } else { 00078 $seq->exception = 'NB.2.1-1'; 00079 } 00080 break; 00081 case 'resumeall_': 00082 if (empty($seq->currentactivity)) { 00083 if ($track = $DB->get_record('scorm_scoes_track', array('scoid'=>$scoid,'userid'=>$userid,'element'=>'suspendedactivity'))) {//I think it's suspend instead of suspendedactivity 00084 $seq->navigation = true; 00085 $seq->sequencing = 'resumeall'; 00086 } else { 00087 $seq->exception = 'NB.2.1-3'; 00088 } 00089 } else { 00090 $seq->exception = 'NB.2.1-1'; 00091 } 00092 break; 00093 case 'continue_': 00094 case 'previous_': 00095 if (!empty($seq->currentactivity)) { 00096 $sco = $seq->currentactivity; 00097 if ($sco->parent != '/') { 00098 if ($parentsco = scorm_get_parent($sco)) { 00099 00100 if (isset($parentsco->flow) && ($parentsco->flow == true)) {//I think it's parentsco 00101 // Current activity is active ! 00102 if (scorm_seq_is('active',$sco->id,$userid)) { 00103 if ($request == 'continue_') { 00104 $seq->navigation = true; 00105 $seq->termination = 'exit'; 00106 $seq->sequencing = 'continue'; 00107 } else { 00108 if (!isset($parentsco->forwardonly) || ($parentsco->forwardonly == false)) { 00109 $seq->navigation = true; 00110 $seq->termination = 'exit'; 00111 $seq->sequencing = 'previous'; 00112 } else { 00113 $seq->exception = 'NB.2.1-5'; 00114 } 00115 } 00116 } 00117 } 00118 00119 } 00120 } 00121 } else { 00122 $seq->exception = 'NB.2.1-2'; 00123 } 00124 break; 00125 case 'forward_': 00126 case 'backward_': 00127 $seq->exception = 'NB.2.1-7' ; 00128 break; 00129 case 'exit_': 00130 case 'abandon_': 00131 if (!empty($seq->currentactivity)) { 00132 // Current activity is active ! 00133 $seq->navigation = true; 00134 $seq->termination = substr($request,0,-1); 00135 $seq->sequencing = 'exit'; 00136 } else { 00137 $seq->exception = 'NB.2.1-2'; 00138 } 00139 case 'exitall_': 00140 case 'abandonall_': 00141 case 'suspendall_': 00142 if (!empty($seq->currentactivity)) { 00143 $seq->navigation = true; 00144 $seq->termination = substr($request,0,-1); 00145 $seq->sequencing = 'exit'; 00146 } else { 00147 $seq->exception = 'NB.2.1-2'; 00148 } 00149 break; 00150 default: 00151 if ($targetsco = $DB->get_record('scorm_scoes', array('scorm'=>$sco->scorm,'identifier'=>$request))) { 00152 if ($targetsco->parent != '/') { 00153 $seq->target = $request; 00154 } else { 00155 if ($parentsco = scorm_get_parent($targetsco)) { 00156 if (!isset($parentsco->choice) || ($parentsco->choice == true)) { 00157 $seq->target = $request; 00158 } 00159 } 00160 } 00161 if ($seq->target != null) { 00162 if (empty($seq->currentactivity)) { 00163 $seq->navigation = true; 00164 $seq->sequencing = 'choice'; 00165 } else { 00166 if (!$sco = scorm_get_sco($scoid)) { 00167 return $seq; 00168 } 00169 if ($sco->parent != $targetsco->parent) { 00170 $ancestors = scorm_get_ancestors($sco); 00171 $commonpos = scorm_find_common_ancestor($ancestors,$targetsco); 00172 if ($commonpos !== false) { 00173 if ($activitypath = array_slice($ancestors,0,$commonpos)) { 00174 foreach ($activitypath as $activity) { 00175 if (scorm_seq_is('active',$activity->id,$userid) && (isset($activity->choiceexit) && ($activity->choiceexit == false))) { 00176 $seq->navigation = false; 00177 $seq->termination = null; 00178 $seq->sequencing = null; 00179 $seq->target = null; 00180 $seq->exception = 'NB.2.1-8'; 00181 return $seq; 00182 } 00183 } 00184 } else { 00185 $seq->navigation = false; 00186 $seq->termination = null; 00187 $seq->sequencing = null; 00188 $seq->target = null; 00189 $seq->exception = 'NB.2.1-9'; 00190 } 00191 } 00192 } 00193 // Current activity is active ! 00194 $seq->navigation = true; 00195 $seq->sequencing = 'choice'; 00196 } 00197 } else { 00198 $seq->exception = 'NB.2.1-10'; 00199 } 00200 } else { 00201 $seq->exception = 'NB.2.1-11'; 00202 } 00203 break; 00204 } 00205 return $seq; 00206 } 00207 00208 function scorm_seq_termination ($seq,$userid) { 00209 if (empty($seq->currentactivity)) { 00210 $seq->termination = false; 00211 $seq->exception = 'TB.2.3-1'; 00212 return $seq; 00213 } 00214 00215 $sco = $seq->currentactivity; 00216 00217 if ((($seq->termination == 'exit') || ($seq->termination == 'abandon')) && !$seq->active) { 00218 $seq->termination = false; 00219 $seq->exception = 'TB.2.3-2'; 00220 return $seq; 00221 } 00222 switch ($seq->termination) { 00223 case 'exit': 00224 scorm_seq_end_attempt($sco,$userid,$seq); 00225 $seq = scorm_seq_exit_action_rules($seq,$userid); 00226 do { 00227 $exit = false;// I think this is false. Originally this was true 00228 $seq = scorm_seq_post_cond_rules($seq,$userid); 00229 if ($seq->termination == 'exitparent') { 00230 if ($sco->parent != '/') { 00231 $sco = scorm_get_parent($sco); 00232 $seq->currentactivity = $sco; 00233 $seq->active = scorm_seq_is('active',$sco->id,$userid); 00234 scorm_seq_end_attempt($sco,$userid,$seq); 00235 $exit = true;//I think it's true. Originally this was false 00236 } else { 00237 $seq->termination = false; 00238 $seq->exception = 'TB.2.3-4'; 00239 return $seq; 00240 } 00241 } 00242 } while (($exit == false) && ($seq->termination == 'exit')); 00243 if ($seq->termination == 'exit') { 00244 $seq->termination = true; 00245 return $seq; 00246 } 00247 case 'exitall': 00248 if ($seq->active) { 00249 scorm_seq_end_attempt($sco,$userid,$seq); 00250 } 00252 00253 00254 if ($ancestors = scorm_get_ancestors($sco)) { 00255 foreach ($ancestors as $ancestor) { 00256 scorm_seq_end_attempt($ancestor,$userid,$seq); 00257 $seq->currentactivity = $ancestor; 00258 } 00259 } 00260 00261 $seq->active = scorm_seq_is('active',$seq->currentactivity->id,$userid); 00262 $seq->termination = true; 00263 $seq->sequencing = exit; 00264 break; 00265 case 'suspendall': 00266 if (($seq->active) || ($seq->suspended)) { 00267 scorm_seq_set('suspended',$sco->id,$userid); 00268 } else { 00269 if ($sco->parent != '/') { 00270 $parentsco = scorm_get_parent($sco); 00271 scorm_seq_set('suspended',$parentsco->id,$userid); 00272 } else { 00273 $seq->termination = false; 00274 $seq->exception = 'TB.2.3-3'; 00275 // return $seq; 00276 } 00277 } 00278 if ($ancestors = scorm_get_ancestors($sco)) { 00279 foreach ($ancestors as $ancestor) { 00280 scorm_seq_set('active',$ancestor->id,$userid,false); 00281 scorm_seq_set('suspended',$ancestor->id,$userid); 00282 $seq->currentactivity = $ancestor; 00283 } 00284 $seq->termination = true; 00285 $seq->sequencing = 'exit'; 00286 } else { 00287 $seq->termination = false; 00288 $seq->exception = 'TB.2.3-5'; 00289 } 00290 break; 00291 case 'abandon': 00292 scorm_seq_set('active',$sco->id,$userid,false); 00293 $seq->active = null; 00294 $seq->termination = true; 00295 break; 00296 case 'abandonall': 00297 if ($ancestors = scorm_get_ancestors($sco)) { 00298 foreach ($ancestors as $ancestor) { 00299 scorm_seq_set('active',$ancestor->id,$userid,false); 00300 $seq->currentactivity = $ancestor; 00301 } 00302 $seq->termination = true; 00303 $seq->sequencing = 'exit'; 00304 } else { 00305 $seq->termination = false; 00306 $seq->exception = 'TB.2.3-6'; 00307 } 00308 break; 00309 default: 00310 $seq->termination = false; 00311 $seq->exception = 'TB.2.3-7'; 00312 break; 00313 } 00314 return $seq; 00315 } 00316 00317 function scorm_seq_end_attempt($sco,$userid,$seq) { 00318 global $DB; 00319 00320 if (scorm_is_leaf($sco)) { 00321 if (!isset($sco->tracked) || ($sco->tracked == 1)) { 00322 if (!scorm_seq_is('suspended',$sco->id,$userid)) { 00323 if (!isset($sco->completionsetbycontent) || ($sco->completionsetbycontent == 0)) { 00324 if (!scorm_seq_is('attemptprogressstatus',$sco->id,$userid,$seq->attempt)) { 00325 // if (!scorm_seq_is('attemptprogressstatus',$sco->id,$userid)) { 00326 scorm_seq_set('attemptprogressstatus',$sco->id,$userid); 00327 scorm_seq_set('attemptcompletionstatus',$sco->id,$userid); 00328 } 00329 } 00330 if (!isset($sco->objectivesetbycontent) || ($sco->objectivesetbycontent == 0)) { 00331 if ($objectives = $DB->get_records('scorm_seq_objective', array('scoid'=>$sco->id))) { 00332 foreach ($objectives as $objective) { 00333 if ($objective->primaryobj) { 00334 //if (!scorm_seq_objective_progress_status($sco,$userid,$objective)) { 00335 if (!scorm_seq_is('objectiveprogressstatus',$sco->id,$userid)) { 00336 scorm_seq_set('objectiveprogressstatus',$sco->id,$userid); 00337 scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid); 00338 } 00339 } 00340 } 00341 } 00342 } 00343 } 00344 } 00345 } else { 00346 if ($children = scorm_get_children($sco)) { 00347 $suspended = false; 00348 foreach ($children as $child) { 00349 if (scorm_seq_is('suspended',$child,$userid)) { 00350 $suspended = true; 00351 break; 00352 } 00353 } 00354 if ($suspended) { 00355 scorm_seq_set('suspended',$sco,$userid); 00356 } else { 00357 scorm_seq_set('suspended',$sco,$userid,false); 00358 } 00359 } 00360 } 00361 scorm_seq_set('active',$sco,$userid,0,false); 00362 scorm_seq_overall_rollup($sco,$userid, $seq); 00363 } 00364 00365 function scorm_seq_is($what, $scoid, $userid, $attempt=0) { 00366 global $DB; 00367 00369 $active = false; 00370 if ($track = $DB->get_record('scorm_scoes_track', array('scoid'=>$scoid,'userid'=>$userid,'attempt'=>$attempt,'element'=>$what))) { 00371 $active = true; 00372 } 00373 return $active; 00374 } 00375 00376 function scorm_seq_set($what, $scoid, $userid, $attempt=0, $value='true') { 00377 global $DB; 00378 00379 $sco = scorm_get_sco($scoid); 00380 00382 if ($value == false) { 00383 $DB->delete_record('scorm_scoes_track', array('scoid'=>$scoid,'userid'=>$userid,'attempt'=>$attempt,'element'=>$what)); 00384 } else { 00385 scorm_insert_track($userid, $sco->scorm, $sco->id, 0, $what, $value); 00386 } 00387 00388 // update grades in gradebook 00389 $scorm = $DB->get_record('scorm', array('id'=>$sco->scorm)); 00390 scorm_update_grades($scorm, $userid, true); 00391 } 00392 00393 function scorm_seq_exit_action_rules($seq,$userid) { 00394 $sco = $seq->currentactivity; 00395 $ancestors = scorm_get_ancestors($sco); 00396 $exittarget = null; 00397 foreach (array_reverse($ancestors) as $ancestor) { 00398 if (scorm_seq_rules_check($ancestor,'exit') != null) { 00399 $exittarget = $ancestor; 00400 break; 00401 } 00402 } 00403 if ($exittarget != null) { 00404 $commons = array_slice($ancestors,0,scorm_find_common_ancestor($ancestors,$exittarget)); 00405 00407 if ($commons) { 00408 foreach ($commons as $ancestor) { 00409 00410 scorm_seq_end_attempt($ancestor,$userid,$seq->attempt); 00411 $seq->currentactivity = $ancestor; 00412 } 00413 } 00414 } 00415 return $seq; 00416 } 00417 00418 function scorm_seq_post_cond_rules($seq,$userid) { 00419 $sco = $seq->currentactivity; 00420 if (!$seq->suspended) { 00421 if ($action = scorm_seq_rules_check($sco,'post') != null) { 00422 switch($action) { 00423 case 'retry': 00424 case 'continue': 00425 case 'previous': 00426 $seq->sequencing = $action; 00427 break; 00428 case 'exitparent': 00429 case 'exitall': 00430 $seq->termination = $action; 00431 break; 00432 case 'retryall': 00433 $seq->termination = 'exitall'; 00434 $seq->sequencing = 'retry'; 00435 break; 00436 } 00437 } 00438 } 00439 return $seq; 00440 } 00441 00442 function scorm_seq_rules_check ($sco, $action){ 00443 global $DB; 00444 00445 $act = null; 00446 if($rules = $DB->get_records('scorm_seq_ruleconds', array('scoid'=>$sco->id,'action'=>$action))) { 00447 foreach ($rules as $rule){ 00448 if($act = scorm_seq_rule_check($sco,$rule)){ 00449 return $act; 00450 } 00451 } 00452 } 00453 return $act; 00454 00455 } 00456 00457 function scorm_seq_rule_check ($sco, $rule){ 00458 global $DB; 00459 00460 $bag = Array(); 00461 $cond = ''; 00462 $ruleconds = $DB->get_records('scorm_seq_rulecond', array('scoid'=>$sco->id,'ruleconditionsid'=>$rule->id)); 00463 foreach ($ruleconds as $rulecond){ 00464 if ($rulecond->operator = 'not') { 00465 if ($rulecond->cond != 'unknown' ){ 00466 $rulecond->cond = 'not'.$rulecond; 00467 } 00468 } 00469 $bag [$rule->id] = $rulecond->cond; 00470 00471 } 00472 if (empty($bag)){ 00473 $cond = 'unknown'; 00474 return $cond; 00475 } 00476 00477 $size= sizeof($bag); 00478 $i=0; 00479 00480 if ($rule->conditioncombination = 'all'){ 00481 foreach ($bag as $con){ 00482 $cond = $cond.' and '.$con; 00483 00484 } 00485 } 00486 else{ 00487 foreach ($bag as $con){ 00488 $cond = $cond.' or '.$con; 00489 } 00490 } 00491 return $cond; 00492 } 00493 00494 00495 function scorm_seq_overall_rollup($sco,$userid, $seq){//Carlos 00496 00497 if ($ancestors = scorm_get_ancestors($sco)) { 00498 foreach ($ancestors as $ancestor) { 00499 if(!scorm_is_leaf($ancestor)){ 00500 scorm_seq_measure_rollup($sco,$userid); 00501 } 00502 scorm_seq_objective_rollup($sco,$userid); 00503 scorm_seq_activity_progress_rollup($sco,$userid, $seq); 00504 00505 } 00506 00507 } 00508 } 00509 00510 /* For this next function I have defined measure weight and measure status as records with the attempt = 0 on the scorm_scoes_track table. According to the page 89 of the SeqNav.pdf those datas give us some information about the progress of the objective*/ 00511 00512 function scorm_seq_measure_rollup($sco,$userid){ 00513 global $DB; 00514 00515 $totalmeasure = 0; //Check if there is something similar in the database 00516 $valid = false;//Same as in the last line 00517 $countedmeasures = 0;//Same too 00518 $targetobjective = null; 00519 $readable = true;//to check if status and measure weight are readable 00520 $objectives = $DB->get_records('scorm_seq_objective', array('scoid'=>$sco->id)); 00521 00522 foreach ($objectives as $objective){ 00523 00524 if ($objective->primaryobj == true){//Objective contributes to rollup I'm using primaryobj field, but not 00525 $targetobjective = $objective; 00526 break; 00527 } 00528 00529 } 00530 00531 if ($targetobjective != null){ 00532 $children = scorm_get_children($sco); 00533 foreach ($children as $child){ 00534 $child = scorm_get_sco ($child); 00535 if (!isset($child->tracked) || ($child->tracked == 1)){ 00536 00537 $rolledupobjective = null;// we set the rolled up activity to undefined 00538 $objectives = $DB->get_records('scorm_seq_objective', array('scoid'=>$child->id)); 00539 foreach ($objectives as $objective){ 00540 if ($objective->primaryobj == true){//Objective contributes to rollup I'm using primaryobj field, but not 00541 $rolledupobjective = $objective; 00542 break; 00543 } 00544 } 00545 if ($rolledupobjective != null){ 00546 $child = scorm_get_sco($child->id); 00547 00548 $countedmeasures = $countedmeasures + ($child->measureweight); 00549 if (!scorm_seq_is('objectivemeasurestatus',$sco->id,$userid)) { 00550 $normalizedmeasure = $DB->get_record('scorm_scoes_track', array('scoid'=>$child->id,'userid'=>$userid,'element'=>'objectivenormalizedmeasure')); 00551 $totalmeasure = $totalmeasure + (($normalizedmeasure->value) * ($child->measureweight)); 00552 $valid = true; 00553 } 00554 00555 00556 00557 } 00558 } 00559 } 00560 00561 00562 if(!$valid){ 00563 00564 scorm_seq_set('objectivemeasurestatus',$sco->id,$userid,false); 00565 00566 } 00567 else{ 00568 if($countedmeasures>0){ 00569 scorm_seq_set('objectivemeasurestatus',$sco->id,$userid); 00570 $val=$totalmeasure/$countedmeasures; 00571 scorm_seq_set('objectivenormalizedmeasure',$sco->id,$userid,$val); 00572 00573 } 00574 else{ 00575 scorm_seq_set('objectivemeasurestatus',$sco->id,$userid,false); 00576 00577 } 00578 } 00579 00580 } 00581 00582 } 00583 00584 function scorm_seq_objective_rollup($sco,$userid){ 00585 global $DB; 00586 00587 scorm_seq_objective_rollup_measure($sco,$userid); 00588 scorm_seq_objective_rollup_rules($sco,$userid); 00589 scorm_seq_objective_rollup_default($sco,$userid); 00590 00591 /* 00592 if($targetobjective->satisfiedbymeasure){ 00593 scorm_seq_objective_rollup_measure($sco,$userid); 00594 } 00595 else{ 00596 if ((scorm_seq_rollup_rule_check($sco,$userid,'incomplete'))|| (scorm_seq_rollup_rule_check($sco,$userid,'completed'))){ 00597 scorm_seq_objective_rollup_rules($sco,$userid); 00598 } 00599 else{ 00600 00601 $rolluprules = $DB->get_record('scorm_seq_rolluprule', array('scoid'=>$sco->id,'userid'=>$userid)); 00602 foreach($rolluprules as $rolluprule){ 00603 $rollupruleconds = $DB->get_records('scorm_seq_rolluprulecond', array('rollupruleid'=>$rolluprule->id)); 00604 foreach($rollupruleconds as $rolluprulecond){ 00605 00606 switch ($rolluprulecond->cond!='satisfied' && $rolluprulecond->cond!='completed' && $rolluprulecond->cond!='attempted'){ 00607 00608 scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid, false); 00609 00610 break; 00611 } 00612 } 00613 00614 00615 } 00616 } 00617 */ 00618 } 00619 00620 function scorm_seq_objective_rollup_measure($sco,$userid){ 00621 global $DB; 00622 00623 $targetobjective = null; 00624 00625 00626 $objectives = $DB->get_records('scorm_seq_objective', array('scoid'=>$sco->id)); 00627 foreach ($objectives as $objective){ 00628 if ($objective->primaryobj == true){ 00629 $targetobjective = $objective; 00630 break; 00631 } 00632 } 00633 if ($targetobjective != null){ 00634 00635 if($targetobjective->satisfiedbymeasure){ 00636 00637 00638 if (!scorm_seq_is('objectiveprogressstatus',$sco->id,$userid)) { 00639 00640 scorm_seq_set('objectiveprogressstatus',$sco->id,$userid,false); 00641 00642 } 00643 00644 else{ 00645 if (scorm_seq_is('active',$sco->id,$userid)) { 00646 $isactive = true; 00647 } 00648 else{ 00649 $isactive = false; 00650 } 00651 00652 $normalizedmeasure = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'objectivenormalizedmeasure')); 00653 00654 $sco = scorm_get_sco ($sco->id); 00655 00656 if (!$isactive || ($isactive && (!isset($sco->measuresatisfactionifactive) || $sco->measuresatisfactionifactive == true))){ 00657 if($normalizedmeasure->value >= $targetobjective->minnormalizedmeasure){ 00658 scorm_seq_set('objectiveprogressstatus',$sco->id,$userid); 00659 scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid); 00660 } 00661 else{ 00662 scorm_seq_set('objectiveprogressstatus',$sco->id,$userid); 00663 scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid,false); 00664 } 00665 } 00666 else{ 00667 00668 scorm_seq_set('objectiveprogressstatus',$sco->id,$userid,false); 00669 00670 } 00671 } 00672 } 00673 } 00674 00675 } 00676 00677 function scorm_seq_objective_rollup_default($sco,$userid){ 00678 global $DB; 00679 00680 if (!(scorm_seq_rollup_rule_check($sco,$userid,'incomplete')) && !(scorm_seq_rollup_rule_check($sco,$userid,'completed'))){ 00681 00682 $rolluprules = $DB->get_record('scorm_seq_rolluprule', array('scoid'=>$sco->id,'userid'=>$userid)); 00683 foreach($rolluprules as $rolluprule){ 00684 $rollupruleconds = $DB->get_records('scorm_seq_rolluprulecond', array('rollupruleid'=>$rolluprule->id)); 00685 foreach($rollupruleconds as $rolluprulecond){ 00686 00687 if ($rolluprulecond->cond!='satisfied' && $rolluprulecond->cond!='completed' && $rolluprulecond->cond!='attempted'){ 00688 00689 scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid, false); 00690 00691 break; 00692 } 00693 } 00694 00695 00696 } 00697 } 00698 00699 } 00700 00701 00702 function scorm_seq_objective_rollup_rules($sco,$userid){ 00703 global $DB; 00704 00705 $targetobjective = null; 00706 00707 $objectives = $DB->get_records('scorm_seq_objective', array('scoid'=>$sco->id)); 00708 foreach ($objectives as $objective){ 00709 if ($objective->primaryobj == true){//Objective contributes to rollup I'm using primaryobj field, but not 00710 $targetobjective = $objective; 00711 break; 00712 } 00713 } 00714 if ($targetobjective != null){ 00715 00716 00717 00718 if(scorm_seq_rollup_rule_check($sco,$userid,'notsatisfied')){//with not satisfied rollup for the activity 00719 00720 00721 scorm_seq_set('objectiveprogressstatus',$sco->id,$userid); 00722 scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid,false); 00723 } 00724 if(scorm_seq_rollup_rule_check($sco,$userid,'satisfied')){//with satisfied rollup for the activity 00725 scorm_seq_set('objectiveprogressstatus',$sco->id,$userid); 00726 scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid); 00727 } 00728 00729 } 00730 00731 } 00732 00733 function scorm_seq_activity_progress_rollup ($sco, $userid, $seq){ 00734 00735 if(scorm_seq_rollup_rule_check($sco,$userid,'incomplete')){ 00736 //incomplete rollup action 00737 scorm_seq_set('attemptcompletionstatus',$sco->id,$userid,false,$seq->attempt); 00738 scorm_seq_set('attemptprogressstatus',$sco->id,$userid,true,$seq->attempt); 00739 00740 } 00741 if(scorm_seq_rollup_rule_check($sco,$userid,'completed')){ 00742 //incomplete rollup action 00743 scorm_seq_set('attemptcompletionstatus',$sco->id,true,$userid); 00744 scorm_seq_set('attemptprogressstatus',$sco->id,true,$userid); 00745 } 00746 00747 } 00748 00749 function scorm_seq_rollup_rule_check ($sco,$userid,$action){ 00750 global $DB; 00751 00752 if($rolluprules = $DB->get_record('scorm_seq_rolluprule', array('scoid'=>$sco->id,'userid'=>$userid,'action'=>$action))) { 00753 00754 $childrenbag = Array (); 00755 $children = scorm_get_children ($sco); 00756 00757 foreach($rolluprules as $rolluprule){ 00758 00759 foreach ($children as $child){ 00760 00761 /*$tracked = $DB->get_records('scorm_scoes_track', array('scoid'=>$child->id,'userid'=>$userid)); 00762 if($tracked && $tracked->attemp != 0){*/ 00763 $child = scorm_get_sco ($child); 00764 if (!isset($child->tracked) || ($child->tracked == 1)){ 00765 00766 if(scorm_seq_check_child ($child,$action,$userid)){ 00767 00768 $rollupruleconds = $DB->get_records('scorm_seq_rolluprulecond', array('rollupruleid'=>$rolluprule->id)); 00769 $evaluate = scorm_seq_evaluate_rollupcond($child,$rolluprule->conditioncombination,$rollupruleconds,$userid); 00770 if ($evaluate=='unknown'){ 00771 array_push($childrenbag,'unknown'); 00772 } 00773 else{ 00774 if($evaluate == true){ 00775 array_push($childrenbag,true); 00776 } 00777 else{ 00778 array_push($childrenbag,false); 00779 } 00780 } 00781 } 00782 } 00783 00784 } 00785 $change = false; 00786 00787 switch ($rolluprule->childactivityset){ 00788 00789 case 'all': 00790 if((array_search(false,$childrenbag)===false)&&(array_search('unknown',$childrenbag)===false)){//I think I can use this condition instead equivalent to OR 00791 $change = true; 00792 } 00793 break; 00794 00795 case 'any': 00796 if(array_search(true,$childrenbag)!==false){//I think I can use this condition instead equivalent to OR 00797 $change = true; 00798 } 00799 break; 00800 00801 case 'none': 00802 if((array_search(true,$childrenbag)===false)&&(array_search('unknown',$childrenbag)===false)){//I think I can use this condition instead equivalent to OR 00803 $change = true; 00804 } 00805 break; 00806 00807 case 'atleastcount': 00808 foreach ($childrenbag as $itm){//I think I can use this condition instead equivalent to OR 00809 $cont = 0; 00810 if($itm === true){ 00811 $cont++; 00812 } 00813 if($cont >= $rolluprule->minimumcount){ 00814 $change = true; 00815 } 00816 } 00817 break; 00818 00819 case 'atleastcount': 00820 foreach ($childrenbag as $itm){//I think I can use this condition instead equivalent to OR 00821 $cont = 0; 00822 if($itm === true){ 00823 $cont++; 00824 } 00825 if($cont >= $rolluprule->minimumcount){ 00826 $change = true; 00827 } 00828 } 00829 break; 00830 00831 case 'atleastpercent': 00832 foreach ($childrenbag as $itm){//I think I can use this condition instead equivalent to OR 00833 $cont = 0; 00834 if($itm === true){ 00835 $cont++; 00836 } 00837 if(($cont/sizeof($childrenbag)) >= $rolluprule->minimumcount){ 00838 $change = true; 00839 } 00840 } 00841 break; 00842 } 00843 if ($change==true){ 00844 return true; 00845 } 00846 } 00847 } 00848 return false; 00849 } 00850 00851 00852 function scorm_seq_evaluate_rollupcond($sco,$conditioncombination,$rollupruleconds,$userid){ 00853 $bag = Array(); 00854 $con = ""; 00855 $val = false; 00856 $unk = false; 00857 foreach($rollupruleconds as $rolluprulecond){ 00858 00859 $condit = scorm_evaluate_condition($rolluprulecond,$sco,$userid); 00860 00861 if($rolluprulecond->operator=='not'){// If operator is not, negate the condition 00862 if ($rolluprulecond->cond != 'unknown'){ 00863 if ($condit){ 00864 $condit = false; 00865 } 00866 else{ 00867 $condit = true; 00868 } 00869 } 00870 else{ 00871 $condit = 'unknown'; 00872 } 00873 array_push($childrenbag,$condit); 00874 } 00875 00876 } 00877 if (empty($bag)){ 00878 return 'unknown'; 00879 } 00880 else{ 00881 $i = 0; 00882 foreach ($bag as $b){ 00883 00884 if ($rolluprulecond->conditioncombination == 'all'){ 00885 00886 $val = true; 00887 if($b == 'unknown'){ 00888 $unk = true; 00889 } 00890 if($b === false){ 00891 return false; 00892 } 00893 } 00894 00895 else{ 00896 00897 $val = false; 00898 00899 if($b == 'unknown'){ 00900 $unk = true; 00901 } 00902 if($b === true){ 00903 return true; 00904 } 00905 } 00906 00907 00908 } 00909 } 00910 if ($unk){ 00911 return 'unknown'; 00912 } 00913 return $val; 00914 00915 } 00916 00917 function scorm_evaluate_condition ($rolluprulecond,$sco,$userid){ 00918 global $DB; 00919 00920 $res = false; 00921 00922 switch ($rolluprulecond->cond){ 00923 00924 case 'satisfied': 00925 if($r=$DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'objectivesatisfiedstatus'))) { 00926 if($r->value == true){ 00927 if ($r=$DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'objectiveprogressstatus'))) { 00928 if($r->value == true){ 00929 $res= true; 00930 } 00931 } 00932 } 00933 } 00934 break; 00935 00936 case 'objectiveStatusKnown': 00937 if ($r=$DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'objectiveprogressstatus'))) { 00938 if($r->value == true){ 00939 $res= true; 00940 } 00941 } 00942 break; 00943 00944 case 'objectiveMeasureKnown': 00945 if ($r = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'objectivemeasurestatus'))) { 00946 if($r->value == true){ 00947 $res = true; 00948 } 00949 00950 } 00951 00952 break; 00953 00954 case 'completed': 00955 if ($r = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'attemptcompletionstatus'))) { 00956 if($r->value){ 00957 if ($r = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'attemptprogressstatus'))) { 00958 if($r->value){ 00959 $res = true; 00960 } 00961 00962 } 00963 } 00964 00965 } 00966 break; 00967 00968 case 'attempted': 00969 if ($r = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'activityprogressstatus'))) { 00970 if($r->value){ 00971 if ($r = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'activityattemptcount'))) { 00972 if($r->value > 0){ 00973 $res = true; 00974 } 00975 00976 } 00977 } 00978 00979 } 00980 break; 00981 00982 00983 case 'attemptLimitExceeded': 00984 if ($r = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'activityprogressstatus'))) { 00985 if($r->value){ 00986 if ($r = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'limitconditionattemptlimitcontrol'))) { 00987 if($r->value){ 00988 if ($r = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'activityattemptcount')) && $r2 = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'limitconditionattemptlimit')) ){ 00989 if($r->value >= $r2->value){ 00990 $res = true; 00991 } 00992 00993 } 00994 00995 } 00996 00997 } 00998 00999 } 01000 01001 } 01002 01003 break; 01004 01005 case 'activityProgressKnown': 01006 01007 if ($r = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'activityprogressstatus'))) { 01008 if($r->value){ 01009 if ($r = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'attemptprogressstatus'))) { 01010 if($r->value){ 01011 $res = true; 01012 } 01013 01014 } 01015 01016 } 01017 01018 } 01019 01020 break; 01021 } 01022 return $res; 01023 01024 } 01025 01026 function scorm_seq_check_child ($sco, $action, $userid){ 01027 global $DB; 01028 01029 $included = false; 01030 $sco=scorm_get_sco($sco->id); 01031 $r = $DB->get_record('scorm_scoes_track', array('scoid'=>$sco->id,'userid'=>$userid,'element'=>'activityattemptcount')); 01032 if ($action == 'satisfied' || $action == 'notsatisfied'){ 01033 if (!$sco->rollupobjectivesatisfied){ 01034 $included = true; 01035 if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifnotsuspended') || ($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifnotsuspended')){ 01036 01037 if (!scorm_seq_is('activityprogressstatus',$sco->id,$userid) || ((($r->value)>0)&& !scorm_seq_is('suspended',$sco->id,$userid))){ 01038 $included = false; 01039 } 01040 01041 } 01042 else{ 01043 if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifattempted') || ($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifattempted')){ 01044 if (!scorm_seq_is('activityprogressstatus',$sco->id,$userid) || (($r->value) == 0)){ 01045 $included = false; 01046 } 01047 } 01048 else{ 01049 if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifnotskipped') || ($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifnotskipped')){ 01050 $rulch = scorm_seq_rules_check($sco, 'skip'); 01051 if ($rulch != null){ 01052 $included = false; 01053 } 01054 } 01055 } 01056 } 01057 } 01058 } 01059 if ($action == 'completed' || $action == 'incomplete'){ 01060 if (!$sco->rollupprogresscompletion){ 01061 $included = true; 01062 01063 if (($action == 'completed' && $sco->requiredforcompleted == 'ifnotsuspended') || ($action == 'incomplete' && $sco->requiredforincomplete == 'ifnotsuspended')){ 01064 01065 if (!scorm_seq_is('activityprogressstatus',$sco->id,$userid) || ( (($r->value)>0)&& !scorm_seq_is('suspended',$sco->id,$userid))){ 01066 $included = false; 01067 } 01068 01069 } 01070 else{ 01071 01072 if (($action == 'completed' && $sco->requiredforcompleted == 'ifattempted') || ($action == 'incomplete' && $sco->requiredforincomplete == 'ifattempted')){ 01073 if (!scorm_seq_is('activityprogressstatus',$sco->id,$userid) || (($r->value)==0)){ 01074 $included = false; 01075 } 01076 01077 } 01078 else{ 01079 if (($action == 'completed' && $sco->requiredforsatisfied == 'ifnotskipped') || ($action == 'incomplete' && $sco->requiredfornotsatisfied == 'ifnotskipped')){ 01080 $rulch = scorm_seq_rules_check($sco, 'skip'); 01081 if ($rulch != null){ 01082 $included = false; 01083 } 01084 } 01085 } 01086 01087 01088 } 01089 01090 } 01091 } 01092 return $included; 01093 01094 01095 } 01096 function scorm_seq_sequencing ($scoid,$userid,$seq) { 01097 01098 switch ($seq->sequencing) { 01099 01100 case 'start': 01101 $seq = scorm_seq_start_sequencing($scoid,$userid,$seq); //We'll see the parameters we have to send, this should update delivery and end 01102 $seq->sequencing = true; 01103 01104 01105 break; 01106 01107 case 'resumeall': 01108 $seq = scorm_seq_resume_all_sequencing($scoid,$userid,$seq); //We'll see the parameters we have to send, this should update delivery and end 01109 $seq->sequencing = true; 01110 01111 01112 01113 break; 01114 01115 case 'exit': 01116 $seq = scorm_seq_exit_sequencing($scoid,$userid,$seq); //We'll see the parameters we have to send, this should update delivery and end 01117 $seq->sequencing = true; 01118 01119 01120 01121 break; 01122 01123 case 'retry': 01124 $seq = scorm_seq_retry_sequencing($scoid,$userid,$seq); //We'll see the parameters we have to send, this should update delivery and end 01125 $seq->sequencing = true; 01126 01127 01128 break; 01129 01130 case 'previous': 01131 $seq = scorm_seq_previous_sequencing($scoid,$userid,$seq);// We'll see the parameters we have to send, this should update delivery and end 01132 $seq->sequencing = true; 01133 01134 01135 break; 01136 01137 case 'choice': 01138 $seq = scorm_seq_choice_sequencing($scoid,$userid,$seq);// We'll see the parameters we have to send, this should update delivery and end 01139 $seq->sequencing = true; 01140 01141 01142 break; 01143 01144 } 01145 01146 if ($seq->exception != null){ 01147 $seq->sequencing = false; 01148 return $seq; 01149 } 01150 01151 $seq->sequencing= true; 01152 return $seq; 01153 } 01154 01155 01156 function scorm_seq_start_sequencing($scoid,$userid,$seq){ 01157 global $DB; 01158 01159 if (!empty($seq->currentactivity)) { 01160 $seq->delivery = null; 01161 $seq->exception = 'SB.2.5-1'; 01162 return $seq; 01163 } 01164 $sco = $DB->get_record('scorm_scoes', array('scoid'=>$scoid,'userid'=>$userid)); 01165 if (($sco->parent == '/') && scorm_is_leaf($sco)) {//if the activity is the root and is leaf 01166 $seq->delivery = $sco; 01167 } 01168 else{ 01169 $ancestors = scorm_get_ancestors($sco); 01170 $ancestorsroot = array_reverse($ancestors); 01171 $res = scorm_seq_flow($ancestorsroot[0],'forward',$seq,true,$userid); 01172 if($res){ 01173 return $res; 01174 } 01175 else{ 01176 //return end and exception 01177 } 01178 } 01179 } 01180 01181 function scorm_seq_resume_all_sequencing($scoid,$userid,$seq){ 01182 global $DB; 01183 01184 if (!empty($seq->currentactivity)){ 01185 $seq->delivery = null; 01186 $seq->exception = 'SB.2.6-1'; 01187 return $seq; 01188 } 01189 $track = $DB->get_record('scorm_scoes_track', array('scoid'=>$scoid,'userid'=>$userid,'element'=>'suspendedactivity')); 01190 if (!$track) { 01191 $seq->delivery = null; 01192 $seq->exception = 'SB.2.6-2'; 01193 return $seq; 01194 } 01195 $seq->delivery = $DB->get_record('scorm_scoes', array('scoid'=>$scoid,'userid'=>$userid));//we assign the sco to the delivery 01196 01197 } 01198 01199 function scorm_seq_continue_sequencing($scoid,$userid,$seq){ 01200 if (empty($seq->currentactivity)) { 01201 $seq->delivery = null; 01202 $seq->exception = 'SB.2.7-1'; 01203 return $seq; 01204 } 01205 $currentact= $seq->currentactivity; 01206 if ($currentact->parent != '/') {//if the activity is the root and is leaf 01207 $parent = scorm_get_parent ($currentact); 01208 01209 if (!isset($parent->flow) || ($parent->flow == false)) { 01210 $seq->delivery = null; 01211 $seq->exception = 'SB.2.7-2'; 01212 return $seq; 01213 } 01214 01215 $res = scorm_seq_flow($currentact,'forward',$seq,false,$userid); 01216 if($res){ 01217 return $res; 01218 } 01219 else{ 01220 //return end and exception 01221 } 01222 01223 } 01224 } 01225 01226 function scorm_seq_previous_sequencing($scoid,$userid,$seq){ 01227 if (empty($seq->currentactivity)) { 01228 $seq->delivery = null; 01229 $seq->exception = 'SB.2.8-1'; 01230 return $seq; 01231 } 01232 01233 $currentact= $seq->currentactivity; 01234 if ($currentact->parent != '/') {//if the activity is the root and is leaf 01235 $parent = scorm_get_parent ($currentact); 01236 if (!isset($parent->flow) || ($parent->flow == false)) { 01237 $seq->delivery = null; 01238 $seq->exception = 'SB.2.8-2'; 01239 return $seq; 01240 } 01241 01242 $res = scorm_seq_flow($currentact,'backward',$seq,false,$userid); 01243 if($res){ 01244 return $res; 01245 } 01246 else{ 01247 //return end and exception 01248 } 01249 01250 } 01251 01252 } 01253 01254 function scorm_seq_exit_sequencing($scoid,$userid,$seq){ 01255 if (empty($seq->currentactivity)) { 01256 $seq->delivery = null; 01257 $seq->exception = 'SB.2.11-1'; 01258 return $seq; 01259 } 01260 01261 if ($seq->active){ 01262 $seq->endsession = false; 01263 $seq->exception = 'SB.2.11-2'; 01264 return $seq; 01265 } 01266 $currentact= $seq->currentactivity; 01267 if ($currentact->parent == '/'){ 01268 $seq->endsession = true; 01269 return $seq; 01270 } 01271 01272 $seq->endsession = false; 01273 return $seq; 01274 } 01275 01276 01277 function scorm_seq_retry_sequencing($scoid,$userid,$seq){ 01278 if (empty($seq->currentactivity)) { 01279 $seq->delivery = null; 01280 $seq->exception = 'SB.2.10-1'; 01281 return $seq; 01282 } 01283 if ($seq->active || $seq->suspended){ 01284 $seq->delivery = null; 01285 $seq->exception = 'SB.2.10-2'; 01286 return $seq; 01287 } 01288 01289 if (!scorm_is_leaf($seq->currentactivity)){ 01290 $res = scorm_seq_flow($seq->currentactivity,'forward',$seq,true,$userid); 01291 if($res != null){ 01292 return $res; 01293 //return deliver 01294 } 01295 else{ 01296 $seq->delivery = null; 01297 $seq->exception = 'SB.2.10-3'; 01298 return $seq; 01299 } 01300 } 01301 else{ 01302 $seq->delivery = $seq->currentactivity; 01303 return $seq; 01304 } 01305 01306 } 01307 01308 function scorm_seq_flow ($candidate,$direction,$seq,$childrenflag,$userid){ 01309 //TODO: $PREVDIRECTION NOT DEFINED YET 01310 01311 $activity=$candidate; 01312 $prevdirection = null; 01313 $seq = scorm_seq_flow_tree_traversal ($activity,$direction,$childrenflag,$prevdirection,$seq,$userid); 01314 if($seq->identifiedactivity == null){//if identifies 01315 $seq->identifiedactivity = $candidate; 01316 $seq->deliverable = false; 01317 return $seq; 01318 } 01319 else{ 01320 $activity = $seq->identifiedactivity; 01321 $seq = scorm_seq_flow_activity_traversal($activity,$userid,$direction,$childrenflag,$prevdirection,$seq,$userid);// 01322 return $seq; 01323 01324 } 01325 } 01326 01327 function scorm_seq_flow_activity_traversal ($activity, $userid, $direction, $childrenflag, $prevdirection, $seq,$userid){//returns the next activity on the tree, traversal direction, control returned to the LTS, (may) exception 01328 $activity = scorm_get_sco ($activity); 01329 $parent = scorm_get_parent ($activity); 01330 if (!isset($parent->flow) || ($parent->flow == false)) { 01331 $seq->deliverable = false; 01332 $seq->exception = 'SB.2.2-1'; 01333 $seq->nextactivity = $activity; 01334 return $seq; 01335 } 01336 01337 $rulch = scorm_seq_rules_check($sco, 'skipped'); // TODO: undefined 01338 if ($rulch != null){ 01339 $seq = scorm_seq_flow_tree_traversal ($activity, $direction, false, $prevdirection, $seq,$userid);//endsession and exception 01340 if ($seq->identifiedactivity == null){ 01341 $seq->deliverable = false; 01342 $seq->nextactivity = $activity; 01343 return $seq; 01344 } 01345 else{ 01346 01347 if ($prevdirection = 'backward' && $seq->traversaldir == 'backward'){ 01348 $seq = scorm_seq_flow_tree_traversal ($activity,$direction,false,null,$seq,$userid); 01349 $seq = scorm_seq_flow_activity_traversal($seq->identifiedactivity, $userid, $direction, $childrenflag, $prevdirection, $seq,$userid); 01350 } 01351 else{ 01352 $seq = scorm_seq_flow_tree_traversal ($activity,$direction,false,null,$seq,$userid); 01353 $seq = scorm_seq_flow_activity_traversal($seq->identifiedactivity, $userid, $direction, $childrenflag, $prevdirection, $seq,$userid); 01354 } 01355 return $seq; 01356 } 01357 } 01358 01359 $ch=scorm_check_activity ($activity,$userid); 01360 01361 if ($ch){ 01362 01363 $seq->deliverable = false; 01364 $seq->exception = 'SB.2.2-2'; 01365 $seq->nextactivity = $activity; 01366 return $seq; 01367 01368 } 01369 01370 if (!scorm_is_leaf($activity)){ 01371 01372 $seq = scorm_seq_flow_tree_traversal ($activity,$direction,true,null,$seq,$userid); 01373 01374 if ($seq->identifiedactivity == null){ 01375 $seq->deliverable = false; 01376 $seq->nextactivity = $activity; 01377 return $seq; 01378 } 01379 01380 else{ 01381 if($direction == 'backward' && $seq->traversaldir == 'forward'){ 01382 $seq = scorm_seq_flow_activity_traversal($seq->identifiedactivity, $userid, 'forward', $childrenflag, 'backward', $seq,$userid); 01383 } 01384 else{ 01385 scorm_seq_flow_activity_traversal($seq->identifiedactivity, $userid, $direction, $childrenflag, null, $seq,$userid); 01386 } 01387 return $seq; 01388 } 01389 01390 } 01391 01392 $seq->deliverable = true; 01393 $seq->nextactivity = $activity; 01394 return $seq; 01395 01396 } 01397 function scorm_seq_flow_tree_traversal ($activity,$direction,$childrenflag,$prevdirection,$seq,$userid){ 01398 01399 $revdirection = false; 01400 $parent = scorm_get_parent ($activity); 01401 $children = scorm_get_available_children ($parent); 01402 $siz = sizeof ($children); 01403 01404 if (($prevdirection != null && $prevdirection == 'backward') && ($children[$siz-1]->id == $activity->id)){ 01405 $direction = 'backward'; 01406 $children[0] = $activity; 01407 $revdirection = true; 01408 } 01409 01410 if($direction = 'forward'){ 01411 $ancestors = scorm_get_ancestors($activity); 01412 $ancestorsroot = array_reverse($ancestors); 01413 $preorder = scorm_get_preorder ($ancestorsroot); 01414 $siz= sizeof ($preorder); 01415 if (($activity->id == $preorder[$siz-1]->id) || (($activity->parent == '/') && !($childrenflag))){ 01416 scorm_seq_terminate_descent($ancestorsroot,$userid); 01417 $seq->endsession = true; 01418 $seq->nextactivity = null; 01419 return $seq; 01420 } 01421 if (scorm_is_leaf ($activity) || !$childrenflag){ 01422 if ($children[$siz-1]->id == $activity->id){ 01423 01424 $seq = scorm_seq_flow_tree_traversal ($parent, $direction, false, null, $seq,$userid); 01425 // I think it's not necessary to do a return in here 01426 } 01427 else{ 01428 $parent = scorm_get_parent($activity); 01429 $children = scorm_get_available_children($parent); 01430 $seq->traversaldir = $direction; 01431 $sib = scorm_get_siblings($activity); 01432 $pos = array_search($sib, $activity); 01433 if ($pos !== false) { 01434 if ($pos != sizeof ($sib)){ 01435 $seq->nextactivity = $sib [$pos+1]; 01436 return $seq; 01437 } 01438 else{ 01439 $ch = scorm_get_children($sib[0]); 01440 $seq->nextactivity = $ch[0]; 01441 return $seq; 01442 } 01443 } 01444 } 01445 } 01446 else{ 01447 if (!empty ($children)){ 01448 $seq->traversaldir = $direction; 01449 $seq->nextactivity = $children[0]; 01450 return $seq; 01451 } 01452 else{ 01453 $seq->traversaldir = null; 01454 $seq->nextactivity = $children[0]; 01455 $seq->exception = 'SB.2.1-2'; 01456 return $seq; 01457 } 01458 } 01459 01460 } 01461 if($direction = 'backward'){ 01462 01463 if ($activity->parent == '/'){ 01464 $seq->traversaldir = null; 01465 $seq->nextactivity = null; 01466 $seq->exception = 'SB.2.1-3'; 01467 return $seq; 01468 } 01469 if (scorm_is_leaf ($activity) || !$childrenflag){ 01470 if (!$revdirection){ 01471 if (isset($parent->forwardonly) && ($parent->forwardonly == true)) { 01472 $seq->traversaldir = null; 01473 $seq->nextactivity = null; 01474 $seq->exception = 'SB.2.1-4'; 01475 return $seq; 01476 } 01477 } 01478 if ($children[0]->id == $activity->id){ 01479 $seq = scorm_seq_flow_tree_traversal ($parent, 'backward', false, null, $seq, $userid); 01480 return $seq; 01481 } 01482 else{ 01483 $ancestors = scorm_get_ancestors($activity); 01484 $ancestorsroot = array_reverse ($ancestors); 01485 $preorder = scorm_get_preorder ($ancestorsroot); 01486 $pos = array_search($preorder, $children[$siz]); 01487 $preord = array_slice($preorder, 0, $pos-1); 01488 $revpreorder = array_reverse($preord); 01489 $position = array_search($revpreorder, $activity); 01490 $seq->nextactivity = $revpreorder[$pos+1]; 01491 $seq->traversaldir = $direction; 01492 return $seq; 01493 } 01494 } 01495 else{ 01496 if (!empty($children)){ 01497 $activity = scorm_get_sco($activity->id); 01498 if (isset($parent->flow) && ($parent->flow == true)) { 01499 $children = scorm_get_children ($activity); 01500 $seq->traversaldir = 'forward'; 01501 $seq->nextactivity = $children[0]; 01502 return $seq; 01503 01504 } 01505 else{ 01506 $children = scorm_get_children ($activity); 01507 $seq->traversaldir = 'backward'; 01508 $seq->nextactivity = $children[sizeof($children)-1]; 01509 return $seq; 01510 } 01511 01512 } 01513 else{ 01514 01515 $seq->traversaldir = null; 01516 $seq->nextactivity = null; 01517 $seq->exception = 'SB.2.1-2'; 01518 return $seq; 01519 } 01520 } 01521 01522 } 01523 01524 01525 } 01526 function scorm_check_activity ($activity,$userid){ 01527 $act = scorm_seq_rules_check($activity,'disabled'); 01528 if ($act != null){ 01529 return true; 01530 } 01531 if(scorm_limit_cond_check ($activity,$userid)){ 01532 return true; 01533 } 01534 return false; 01535 01536 01537 } 01538 01539 function scorm_limit_cond_check ($activity,$userid){ 01540 global $DB; 01541 01542 if (isset($activity->tracked) && ($activity->tracked == 0)){ 01543 01544 return false; 01545 } 01546 01547 if (scorm_seq_is('active',$activity->id,$userid) || scorm_seq_is('suspended',$activity->id,$userid)){ 01548 return false; 01549 } 01550 01551 if (!isset($activity->limitcontrol) || ($activity->limitcontrol == 1)){ 01552 $r = $DB->get_record('scorm_scoes_track', array('scoid'=>$activity->id,'userid'=>$userid,'element'=>'activityattemptcount')); 01553 if (scorm_seq_is('activityprogressstatus',$activity->id,$userid) && ($r->value >=$activity->limitattempt)){ 01554 return true; 01555 } 01556 } 01557 01558 if (!isset($activity->limitabsdurcontrol) || ($activity->limitabsdurcontrol == 1)){ 01559 $r = $DB->get_record('scorm_scoes_track', array('scoid'=>$activity->id,'userid'=>$userid,'element'=>'activityabsoluteduration')); 01560 if (scorm_seq_is('activityprogressstatus',$activity->id,$userid) && ($r->value >=$activity->limitabsduration)){ 01561 return true; 01562 } 01563 } 01564 01565 if (!isset($activity->limitexpdurcontrol) || ($activity->limitexpdurcontrol == 1)){ 01566 $r = $DB->get_record('scorm_scoes_track', array('scoid'=>$activity->id,'userid'=>$userid,'element'=>'activityexperiencedduration')); 01567 if (scorm_seq_is('activityprogressstatus',$activity->id,$userid) && ($r->value >=$activity->limitexpduration)){ 01568 return true; 01569 } 01570 } 01571 01572 if (!isset($activity->limitattabsdurcontrol) || ($activity->limitattabsdurcontrol == 1)){ 01573 $r = $DB->get_record('scorm_scoes_track', array('scoid'=>$activity->id,'userid'=>$userid,'element'=>'attemptabsoluteduration')); 01574 if (scorm_seq_is('activityprogressstatus',$activity->id,$userid) && ($r->value >=$activity->limitattabsduration)){ 01575 return true; 01576 } 01577 } 01578 01579 if (!isset($activity->limitattexpdurcontrol) || ($activity->limitattexpdurcontrol == 1)){ 01580 $r = $DB->get_record('scorm_scoes_track', array('scoid'=>$activity->id,'userid'=>$userid,'element'=>'attemptexperiencedduration')); 01581 if (scorm_seq_is('activityprogressstatus',$activity->id,$userid) && ($r->value >=$activity->limitattexpduration)){ 01582 return true; 01583 } 01584 } 01585 01586 if (!isset($activity->limitbegincontrol) || ($activity->limitbegincontrol == 1)){ 01587 $r = $DB->get_record('scorm_scoes_track', array('scoid'=>$activity->id,'userid'=>$userid,'element'=>'begintime')); 01588 if (time()>=$activity->limitbegintime){ 01589 return true; 01590 } 01591 } 01592 01593 if (!isset($activity->limitbegincontrol) || ($activity->limitbegincontrol == 1)){ 01594 if (time()<$activity->limitbegintime){ 01595 return true; 01596 } 01597 } 01598 01599 if (!isset($activity->limitendcontrol) || ($activity->limitendcontrol == 1)){ 01600 01601 if (time()>$activity->limitendtime){ 01602 return true; 01603 } 01604 } 01605 return false; 01606 01607 01608 } 01609 01610 01611 function scorm_seq_choice_sequencing($sco,$userid,$seq){ 01612 01613 $avchildren = Array (); 01614 $comancestor = null; 01615 $traverse = null; 01616 01617 if ($sco == null){ 01618 $seq->delivery = null; 01619 $seq->exception = 'SB.2.9-1'; 01620 return $seq; 01621 } 01622 01623 $ancestors = scorm_get_ancestors($sco); 01624 $arrpath = array_reverse($ancestors); 01625 array_push ($arrpath,$sco);//path from the root to the target 01626 01627 foreach ($arrpath as $activity){ 01628 01629 if ($activity->parent != '/') { 01630 $avchildren = scorm_get_available_children (scorm_get_parent($activity)); 01631 $position = array_search($avchildren, $activity); 01632 if ($position !== false){ 01633 $seq->delivery = null; 01634 $seq->exception = 'SB.2.9-2'; 01635 return $seq; 01636 } 01637 } 01638 01639 if (scorm_seq_rules_check($activity,'hidefromchoice' != null)){ 01640 01641 $seq->delivery = null; 01642 $seq->exception = 'SB.2.9-3'; 01643 return $seq; 01644 01645 } 01646 01647 } 01648 01649 if ($sco->parent != '/') { 01650 $parent = scorm_sco_get_parent ($sco); 01651 if ( isset($parent->choice) && ($parent->choice == false)){ 01652 $seq->delivery = null; 01653 $seq->exception = 'SB.2.9-4'; 01654 return $seq; 01655 } 01656 } 01657 01658 if ($seq->currentactivity != null){ 01659 $commonpos = scorm_find_common_ancestor($ancestors,$seq->currentactivity); 01660 $comancestor = $arrpath [$commonpos]; 01661 } 01662 else{ 01663 $comancestor = $arrpath [0]; 01664 } 01665 01666 if($seq->currentactivity === $sco) { 01667 break; 01668 } 01669 01670 $sib = scorm_get_siblings($seq->currentactivity); 01671 $pos = array_search($sib, $sco); 01672 01673 if ($pos !== false){ 01674 01675 $siblings = array_slice($sib, 0, $pos-1); 01676 01677 if (empty($siblings)){ 01678 01679 $seq->delivery = null; 01680 $seq->exception = 'SB.2.9-5'; 01681 return $seq; 01682 01683 } 01684 01685 $children = scorm_get_children (scorm_get_parent ($sco)); 01686 $pos1 = array_search($children, $sco); 01687 $pos2 = array_search($seq->currentactivity, $sco); 01688 if ($pos1>$pos2){ 01689 $traverse = 'forward'; 01690 } 01691 else{ 01692 $traverse = 'backward'; 01693 } 01694 01695 foreach ($siblings as $sibling){ 01696 $seq = scorm_seq_choice_activity_traversal($sibling,$userid,$seq,$traverse); 01697 if(!$seq->reachable){ 01698 $seq->delivery = null; 01699 return $seq; 01700 } 01701 } 01702 break; 01703 01704 } 01705 01706 if($seq->currentactivity == null || $seq->currentactivity == $comancestor){ 01707 $commonpos = scorm_find_common_ancestor($ancestors,$seq->currentactivity); 01708 $comtarget = array_slice($ancestors, 1,$commonpos-1);//path from the common ancestor to the target activity 01709 $comtarget = array_reverse($comtarget); 01710 01711 if (empty($comtarget)){ 01712 $seq->delivery = null; 01713 $seq->exception = 'SB.2.9-5'; 01714 return $seq; 01715 } 01716 foreach ($comtarget as $act){ 01717 $seq = scorm_seq_choice_activity_traversal($act,$userid,$seq,'forward'); 01718 if(!$seq->reachable){ 01719 $seq->delivery = null; 01720 return $seq; 01721 } 01722 $act = scorm_get_sco ($acti->id); 01723 if(scorm_seq_is('active',$act->id,$userid) && ($act->id != $comancestor->id && $act->preventactivation)){//adlseq:can i write it like another property for the $seq object? 01724 $seq->delivery = null; 01725 $seq->exception = 'SB.2.9-6'; 01726 return $seq; 01727 } 01728 } 01729 break; 01730 01731 } 01732 01733 if ($comancestor->id == $sco->id){ 01734 01735 $ancestorscurrent = scorm_get_ancestors($seq->currentactivity); 01736 $possco = array_search ($ancestorscurrent, $sco); 01737 $curtarget = array_slice($ancestorscurrent,0,$possco);//path from the current activity to the target 01738 01739 if (empty($curtarget)){ 01740 $seq->delivery = null; 01741 $seq->exception = 'SB.2.9-5'; 01742 return $seq; 01743 } 01744 $i=0; 01745 foreach ($curtarget as $activ){ 01746 $i++; 01747 if ($i != sizeof($curtarget)){ 01748 if ( isset($activ->choiceexit) && ($activ->choiceexit == false)){ 01749 $seq->delivery = null; 01750 $seq->exception = 'SB.2.9-7'; 01751 return $seq; 01752 } 01753 } 01754 } 01755 break; 01756 } 01757 01758 if (array_search ($ancestors, $comancestor)!== false){ 01759 $ancestorscurrent = scorm_get_ancestors($seq->currentactivity); 01760 $commonpos = scorm_find_common_ancestor($ancestors,$sco); 01761 $curcommon = array_slice($ancestorscurrent,0,$commonpos-1); 01762 if(empty($curcommon)){ 01763 $seq->delivery = null; 01764 $seq->exception = 'SB.2.9-5'; 01765 return $seq; 01766 } 01767 01768 $constrained = null; 01769 foreach ($curcommon as $acti){ 01770 $acti = scorm_get_sco($acti->id); 01771 if ( isset($acti->choiceexit) && ($acti->choiceexit == false)){ 01772 $seq->delivery = null; 01773 $seq->exception = 'SB.2.9-7'; 01774 return $seq; 01775 } 01776 if ($constrained == null){ 01777 if($acti->constrainchoice == true){ 01778 $constrained = $acti; 01779 } 01780 } 01781 } 01782 if ($constrained != null){ 01783 $fwdir = scorm_get_preorder($constrained); 01784 01785 if(array_search ($fwdir, $sco)!== false){ 01786 $traverse = 'forward'; 01787 } 01788 else{ 01789 $traverse = 'backward'; 01790 } 01791 $seq = scorm_seq_choice_flow ($constrained, $traverse, $seq); 01792 $actconsider = $seq->identifiedactivity; 01793 $avdescendents = Array(); 01794 $avdescendents= scorm_get_available_descendents ($actconsider); 01795 if (array_search ($avdescendents, $sco) !== false && $sco->id != $actconsider->id && $constrained->id != $sco->id ){ 01796 $seq->delivery = null; 01797 $seq->exception = 'SB.2.9-8'; 01798 return $seq; 01799 } 01800 01801 //CONTINUE 11.5.5 01802 } 01803 01804 $commonpos = scorm_find_common_ancestor($ancestors,$seq->currentactivity); 01805 $comtarget = array_slice($ancestors, 1,$commonpos-1);//path from the common ancestor to the target activity 01806 $comtarget = array_reverse($comtarget); 01807 01808 if (empty($comtarget)){ 01809 $seq->delivery = null; 01810 $seq->exception = 'SB.2.9-5'; 01811 return $seq; 01812 } 01813 01814 $fwdir = scorm_get_preorder($seq->currentactivity); 01815 01816 if(array_search ($fwdir, $sco)!== false){ 01817 01818 foreach ($comtarget as $act){ 01819 $seq = scorm_seq_choice_activity_traversal($act,$userid,$seq,'forward'); 01820 if(!$seq->reachable){ 01821 $seq->delivery = null; 01822 return $seq; 01823 } 01824 $act = scorm_get_sco($act->id); 01825 if(scorm_seq_is('active',$act->id,$userid) && ($act->id != $comancestor->id && ($act->preventactivation == true))){ 01826 $seq->delivery = null; 01827 $seq->exception = 'SB.2.9-6'; 01828 return $seq; 01829 } 01830 } 01831 01832 } 01833 else{ 01834 foreach ($comtarget as $act){ 01835 $act = scorm_get_sco($act->id); 01836 if(scorm_seq_is('active',$act->id,$userid) && ($act->id != $comancestor->id && ($act->preventactivation==true))){ 01837 $seq->delivery = null; 01838 $seq->exception = 'SB.2.9-6'; 01839 return $seq; 01840 } 01841 } 01842 } 01843 break; 01844 } 01845 01846 if(scorm_is_leaf ($sco)){ 01847 $seq->delivery = $sco; 01848 $seq->exception = 'SB.2.9-6'; 01849 return $seq; 01850 } 01851 01852 $seq = scorm_seq_flow ($sco,'forward',$seq,true,$userid); 01853 if ($seq->deliverable == false){ 01854 scorm_terminate_descendent_attempts($comancestor,$userid,$seq); 01855 scorm_seq_end_attempt($comancestor,$userid,$seq->attempt); 01856 $seq->currentactivity = $sco; 01857 $seq->delivery = null; 01858 $seq->exception = 'SB.2.9-9'; 01859 return $seq; 01860 01861 } 01862 else{ 01863 return $seq; 01864 } 01865 01866 } 01867 01868 function scorm_seq_choice_flow ($constrained, $traverse, $seq){ 01869 $seq = scorm_seq_choice_flow_tree ($constrained, $traverse, $seq); 01870 if ($seq->identifiedactivity == null){ 01871 $seq->identifiedactivity = $constrained; 01872 return $seq; 01873 } 01874 else{ 01875 return $seq; 01876 } 01877 } 01878 01879 function scorm_seq_choice_flow_tree ($constrained, $traverse, $seq){ 01880 $islast = false; 01881 $parent = scorm_get_parent ($constrained); 01882 if ($traverse== 'forward'){ 01883 $preord = scorm_get_preorder ($constrained); 01884 if (sizeof($preorder) == 0 || (sizeof($preorder) == 0 && $preorder[0]->id = $constrained->id)){ // TODO: undefined 01885 $islast = true;//the function is the last activity available 01886 } 01887 if ($constrained->parent == '/' || $islast){ 01888 $seq->nextactivity = null; 01889 return $seq; 01890 } 01891 $avchildren = scorm_get_available_children ($parent);//available children 01892 if ($avchildren [sizeof($avchildren)-1]->id == $constrained->id){ 01893 $seq = scorm_seq_choice_flow_tree ($parent, 'forward', $seq); 01894 return $seq; 01895 } 01896 else{ 01897 $i=0; 01898 while($i < sizeof($avchildren)){ 01899 if ($avchildren [$i]->id == $constrained->id){ 01900 $seq->nextactivity = $avchildren [$i+1]; 01901 return $seq; 01902 } 01903 else{ 01904 $i++; 01905 } 01906 } 01907 } 01908 01909 } 01910 01911 if ($traverse== 'backward'){ 01912 if($constrained->parent == '/' ){ 01913 $seq->nextactivity = null; 01914 return $seq; 01915 } 01916 01917 $avchildren = scorm_get_available_children ($parent);//available children 01918 if ($avchildren [0]->id == $constrained->id){ 01919 $seq = scorm_seq_choice_flow_tree ($parent, 'backward', $seq); 01920 return $seq; 01921 } 01922 else{ 01923 $i=sizeof($avchildren)-1; 01924 while($i >=0){ 01925 if ($avchildren [$i]->id == $constrained->id){ 01926 $seq->nextactivity = $avchildren [$i-1]; 01927 return $seq; 01928 } 01929 else{ 01930 $i--; 01931 } 01932 } 01933 } 01934 } 01935 } 01936 function scorm_seq_choice_activity_traversal($activity,$userid,$seq,$direction){ 01937 01938 if($direction == 'forward'){ 01939 01940 $act = scorm_seq_rules_check($activity,'stopforwardtraversal'); 01941 01942 if($act != null){ 01943 $seq->reachable = false; 01944 $seq->exception = 'SB.2.4-1'; 01945 return $seq; 01946 } 01947 $seq->reachable = false; 01948 return $seq; 01949 } 01950 01951 if($direction == 'backward'){ 01952 $parentsco = scorm_get_parent($activity); 01953 if($parentsco!= null){ 01954 if (isset($parentsco->forwardonly) && ($parentsco->forwardonly == true)){ 01955 $seq->reachable = false; 01956 $seq->exception = 'SB.2.4-2'; 01957 return $seq; 01958 } 01959 else{ 01960 $seq->reachable = false; 01961 $seq->exception = 'SB.2.4-3'; 01962 return $seq; 01963 } 01964 } 01965 } 01966 $seq->reachable = true; 01967 return $seq; 01968 01969 } 01970 01971 //Delivery Request Process 01972 01973 function scorm_sequencing_delivery($scoid,$userid,$seq){ 01974 01975 if(!scorm_is_leaf ($seq->delivery)){ 01976 $seq->deliveryvalid = false; 01977 $seq->exception = 'DB.1.1-1'; 01978 return $seq; 01979 } 01980 $ancestors = scorm_get_ancestors($seq->delivery); 01981 $arrpath = array_reverse($ancestors); 01982 array_push ($arrpath,$seq->delivery);//path from the root to the target 01983 01984 if (empty($arrpath)){ 01985 $seq->deliveryvalid = false; 01986 $seq->exception = 'DB.1.1-2'; 01987 return $seq; 01988 } 01989 01990 foreach ($arrpath as $activity){ 01991 if(scorm_check_activity ($activity,$userid)){ 01992 $seq->deliveryvalid = false; 01993 $seq->exception = 'DB.1.1-3'; 01994 return $seq; 01995 } 01996 } 01997 01998 $seq->deliveryvalid = true; 01999 return $seq; 02000 02001 } 02002 02003 function scorm_content_delivery_environment ($seq,$userid){ 02004 global $DB; 02005 02006 $act = $seq->currentactivity; 02007 if(scorm_seq_is('active',$act->id,$userid)){ 02008 $seq->exception = 'DB.2-1'; 02009 return $seq; 02010 } 02011 $track = $DB->get_record('scorm_scoes_track', array('scoid'=>$act->id,'userid'=>$userid,'element'=>'suspendedactivity')); 02012 if ($track != null){ 02013 $seq = scorm_clear_suspended_activity($seq->delivery, $seq, $userid); 02014 02015 } 02016 $seq = scorm_terminate_descendent_attempts ($seq->delivery,$userid,$seq); 02017 $ancestors = scorm_get_ancestors($seq->delivery); 02018 $arrpath = array_reverse($ancestors); 02019 array_push ($arrpath,$seq->delivery); 02020 foreach ($arrpath as $activity){ 02021 if(!scorm_seq_is('active',$activity->id,$userid)){ 02022 if(!isset($activity->tracked) || ($activity->tracked == 1)){ 02023 if(!scorm_seq_is('suspended',$activity->id,$userid)){ 02024 $r = $DB->get_record('scorm_scoes_track', array('scoid'=>$activity->id,'userid'=>$userid,'element'=>'activityattemptcount')); 02025 $r->value = ($r->value)+1; 02026 $DB->update_record ('scorm_scoes_track',$r); 02027 if ($r->value == 1){ 02028 scorm_seq_set('activityprogressstatus', $activity->id, $userid, 'true'); 02029 } 02030 scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectiveprogressstatus', 'false'); 02031 scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectivesatisfiedstatus', 'false'); 02032 scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectivemeasurestatus', 'false'); 02033 scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectivenormalizedmeasure', 0.0); 02034 02035 scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptprogressstatus', 'false'); 02036 scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptcompletionstatus', 'false'); 02037 scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptabsoluteduration', 0.0); 02038 scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptexperiencedduration', 0.0); 02039 scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptcompletionamount', 0.0); 02040 } 02041 } 02042 scorm_seq_set('active', $activity->id, $userid, 'true'); 02043 } 02044 } 02045 $seq->delivery = $seq->currentactivity; 02046 scorm_seq_set('suspendedactivity', $activity->id, $userid, 'false'); 02047 02048 //ONCE THE DELIVERY BEGINS (How should I check that?) 02049 02050 if(isset($activity->tracked) || ($activity->tracked == 0)){ 02051 //How should I track the info and what should I do to not record the information for the activity during delivery? 02052 $atabsdur = $DB->get_record('scorm_scoes_track', array('scoid'=>$activity->id,'userid'=>$userid,'element'=>'attemptabsoluteduration')); 02053 $atexpdur = $DB->get_record('scorm_scoes_track', array('scoid'=>$activity->id,'userid'=>$userid,'element'=>'attemptexperiencedduration')); 02054 } 02055 return $seq; 02056 02057 02058 } 02059 function scorm_clear_suspended_activity($act,$seq, $userid){ 02060 global $DB; 02061 $currentact= $seq->currentactivity; 02062 $track = $DB->get_record('scorm_scoes_track', array('scoid'=>$currentact->id,'userid'=>$userid,'element'=>'suspendedactivity')); // TODO: undefined 02063 if ($track != null){ 02064 $ancestors = scorm_get_ancestors($act); 02065 $commonpos = scorm_find_common_ancestor($ancestors,$currentact); 02066 if ($commonpos !== false) { 02067 if ($activitypath = array_slice($ancestors,0,$commonpos)) { 02068 if (!empty ($activitypath)){ 02069 02070 foreach ($activitypath as $activity) { 02071 if (scorm_is_leaf($activity)){ 02072 scorm_seq_set('suspended',$activity->id,$userid,false); 02073 } 02074 else{ 02075 $children = scorm_get_children($activity); 02076 $bool= false; 02077 foreach ($children as $child){ 02078 if(scorm_seq_is('suspended',$child->id,$userid)){ 02079 $bool= true; 02080 } 02081 } 02082 if(!$bool){ 02083 scorm_seq_set('suspended',$activity->id,$userid,false); 02084 } 02085 } 02086 } 02087 } 02088 } 02089 } 02090 scorm_seq_set('suspendedactivity',$act->id,$userid,false); 02091 02092 } 02093 } 02094 02095 function scorm_select_children_process($scoid,$userid){ 02096 global $DB; 02097 02098 $sco = scorm_get_sco($scoid); 02099 if (!scorm_is_leaf($sco)){ 02100 if(!scorm_seq_is('suspended',$scoid,$userid) && !scorm_seq_is('active',$scoid,$userid)){ 02101 $r = $DB->get_record('scorm_scoes_track', array('scoid'=>$scoid,'userid'=>$userid,'element'=>'selectiontiming')); 02102 02103 switch($r->value) { 02104 02105 case 'oneachnewattempt': 02106 case 'never': 02107 break; 02108 02109 case 'once': 02110 if(!scorm_seq_is('activityprogressstatus',$scoid,$userid)){ 02111 if(scorm_seq_is('selectioncountsstatus',$scoid,$userid)){ 02112 $childlist = ''; 02113 $res = $DB->get_record('scorm_scoes_track', array('scoid'=>$scoid,'userid'=>$userid,'element'=>'selectioncount')); 02114 $i = ($res->value)-1; 02115 $children = scorm_get_children ($sco); 02116 02117 while ($i>=0){ 02118 $pos = array_rand($children); 02119 array_push($childlist,$children [$pos]); 02120 array_splice($children,$pos,1); 02121 $i--; 02122 } 02123 sort ($childlist); 02124 $clist = serialize ($childlist); 02125 scorm_seq_set('availablechildren', $scoid, $userid, false); 02126 scorm_seq_set('availablechildren', $scoid, $userid, $clist); 02127 02128 02129 } 02130 } 02131 break; 02132 02133 } 02134 02135 } 02136 } 02137 } 02138 02139 function scorm_randomize_children_process($scoid,$userid){ 02140 global $DB; 02141 02142 $sco = scorm_get_sco($scoid); 02143 if (!scorm_is_leaf($sco)){ 02144 if(!scorm_seq_is('suspended',$scoid,$userid) && !scorm_seq_is('active',$scoid,$userid)){ 02145 $r = $DB->get_record('scorm_scoes_track', array('scoid'=>$scoid,'userid'=>$userid,'element'=>'randomizationtiming')); 02146 02147 switch($r->value) { 02148 02149 02150 case 'never': 02151 break; 02152 02153 case 'oneachnewattempt': 02154 case 'once': 02155 if(!scorm_seq_is('activityprogressstatus',$scoid,$userid)){ 02156 if(scorm_seq_is('randomizechildren',$scoid,$userid)){ 02157 $childlist = array(); 02158 $res = scorm_get_available_children($sco); 02159 $i = sizeof($res)-1; 02160 $children = $res->value; 02161 02162 while ($i>=0){ 02163 $pos = array_rand($children); 02164 array_push($childlist,$children [$pos]); 02165 array_splice($children,$pos,1); 02166 $i--; 02167 } 02168 02169 $clist = serialize ($childlist); 02170 scorm_seq_set('availablechildren', $scoid, $userid, false); 02171 scorm_seq_set('availablechildren', $scoid, $userid, $clist); 02172 02173 02174 } 02175 } 02176 break; 02177 02178 02179 02180 } 02181 02182 } 02183 } 02184 } 02185 02186 function scorm_terminate_descendent_attempts ($activity,$userid,$seq){ 02187 $ancestors = scorm_get_ancestors($seq->currentactivity); 02188 $commonpos = scorm_find_common_ancestor($ancestors,$activity); 02189 if ($commonpos !== false) { 02190 if ($activitypath = array_slice($ancestors,1,$commonpos-2)) { 02191 if (!empty ($activitypath)){ 02192 02193 foreach ($activitypath as $sco) { 02194 scorm_seq_end_attempt($sco,$userid,$seq->attempt); 02195 02196 } 02197 } 02198 } 02199 } 02200 } 02201 02202 function scorm_sequencing_exception($seq){ 02203 global $OUTPUT; 02204 if($seq->exception != null){ 02205 switch($seq->exception){ 02206 02207 case 'NB.2.1-1': 02208 echo $OUTPUT->notification("Sequencing session has already begun"); 02209 break; 02210 case 'NB.2.1-2': 02211 echo $OUTPUT->notification("Sequencing session has not begun"); 02212 break; 02213 case 'NB.2.1-3': 02214 echo $OUTPUT->notification("Suspended activity is not defined"); 02215 break; 02216 case 'NB.2.1-4': 02217 echo $OUTPUT->notification("Flow Sequencing Control Model Violation"); 02218 break; 02219 case 'NB.2.1-5': 02220 echo $OUTPUT->notification("Flow or Forward only Sequencing Control Model Violation"); 02221 break; 02222 case 'NB.2.1-6': 02223 echo $OUTPUT->notification("No activity is previous to the root"); 02224 break; 02225 case 'NB.2.1-7': 02226 echo $OUTPUT->notification("Unsupported Navigation Request"); 02227 break; 02228 case 'NB.2.1-8': 02229 echo $OUTPUT->notification("Choice Exit Sequencing Control Model Violation"); 02230 break; 02231 case 'NB.2.1-9': 02232 echo $OUTPUT->notification("No activities to consider"); 02233 break; 02234 case 'NB.2.1-10': 02235 echo $OUTPUT->notification("Choice Sequencing Control Model Violation"); 02236 break; 02237 case 'NB.2.1-11': 02238 echo $OUTPUT->notification("Target Activity does not exist"); 02239 break; 02240 case 'NB.2.1-12': 02241 echo $OUTPUT->notification("Current Activity already terminated"); 02242 break; 02243 case 'NB.2.1-13': 02244 echo $OUTPUT->notification("Undefined Navigation Request"); 02245 break; 02246 02247 case 'TB.2.3-1': 02248 echo $OUTPUT->notification("Current Activity already terminated"); 02249 break; 02250 case 'TB.2.3-2': 02251 echo $OUTPUT->notification("Current Activity already terminated"); 02252 break; 02253 case 'TB.2.3-4': 02254 echo $OUTPUT->notification("Current Activity already terminated"); 02255 break; 02256 case 'TB.2.3-5': 02257 echo $OUTPUT->notification("Nothing to suspend; No active activities"); 02258 break; 02259 case 'TB.2.3-6': 02260 echo $OUTPUT->notification("Nothing to abandon; No active activities"); 02261 break; 02262 02263 case 'SB.2.1-1': 02264 echo $OUTPUT->notification("Last activity in the tree"); 02265 break; 02266 case 'SB.2.1-2': 02267 echo $OUTPUT->notification("Cluster has no available children"); 02268 break; 02269 case 'SB.2.1-3': 02270 echo $OUTPUT->notification("No activity is previous to the root"); 02271 break; 02272 case 'SB.2.1-4': 02273 echo $OUTPUT->notification("Forward Only Sequencing Control Model Violation"); 02274 break; 02275 02276 case 'SB.2.2-1': 02277 echo $OUTPUT->notification("Flow Sequencing Control Model Violation"); 02278 break; 02279 case 'SB.2.2-2': 02280 echo $OUTPUT->notification("Activity unavailable"); 02281 break; 02282 02283 case 'SB.2.3-1': 02284 echo $OUTPUT->notification("Forward Traversal Blocked"); 02285 break; 02286 case 'SB.2.3-2': 02287 echo $OUTPUT->notification("Forward Only Sequencing Control Model Violation"); 02288 break; 02289 case 'SB.2.3-3': 02290 echo $OUTPUT->notification("No activity is previous to the root"); 02291 break; 02292 02293 case 'SB.2.5-1': 02294 echo $OUTPUT->notification("Sequencing session has already begun"); 02295 break; 02296 02297 case 'SB.2.6-1': 02298 echo $OUTPUT->notification("Sequencing session has already begun"); 02299 break; 02300 case 'SB.2.6-2': 02301 echo $OUTPUT->notification("No Suspended activity is defined"); 02302 break; 02303 02304 case 'SB.2.7-1': 02305 echo $OUTPUT->notification("Sequencing session has not begun"); 02306 break; 02307 case 'SB.2.7-2': 02308 echo $OUTPUT->notification("Flow Sequencing Control Model Violation"); 02309 break; 02310 02311 case 'SB.2.8-1': 02312 echo $OUTPUT->notification("Sequencing session has not begun"); 02313 break; 02314 case 'SB.2.8-2': 02315 echo $OUTPUT->notification("Flow Sequencing Control Model Violation"); 02316 break; 02317 02318 case 'SB.2.9-1': 02319 echo $OUTPUT->notification("No target for Choice"); 02320 break; 02321 case 'SB.2.9-2': 02322 echo $OUTPUT->notification("Target Activity does not exist or is unavailable"); 02323 break; 02324 case 'SB.2.9-3': 02325 echo $OUTPUT->notification("Target Activity hidden from choice"); 02326 break; 02327 case 'SB.2.9-4': 02328 echo $OUTPUT->notification("Choice Sequencing Control Model Violation"); 02329 break; 02330 case 'SB.2.9-5': 02331 echo $OUTPUT->notification("No activities to consider"); 02332 break; 02333 case 'SB.2.9-6': 02334 echo $OUTPUT->notification("Unable to activate target; target is not a child of the Current Activity"); 02335 break; 02336 case 'SB.2.9-7': 02337 echo $OUTPUT->notification("Choice Exit Sequencing Control Model Violation"); 02338 break; 02339 case 'SB.2.9-8': 02340 echo $OUTPUT->notification("Unable to choose target activity - constrained choice"); 02341 break; 02342 case 'SB.2.9-9': 02343 echo $OUTPUT->notification("Choice Request Prevented by Flow-only Activity"); 02344 break; 02345 02346 case 'SB.2.10-1': 02347 echo $OUTPUT->notification("Sequencing session has not begun"); 02348 break; 02349 case 'SB.2.10-2': 02350 echo $OUTPUT->notification("Current Activity is active or suspended"); 02351 break; 02352 case 'SB.2.10-3': 02353 echo $OUTPUT->notification("Flow Sequencing Control Model Violation"); 02354 break; 02355 02356 case 'SB.2.11-1': 02357 echo $OUTPUT->notification("Sequencing session has not begun"); 02358 break; 02359 case 'SB.2.11-2': 02360 echo $OUTPUT->notification("Current Activity has not been terminated"); 02361 break; 02362 02363 case 'SB.2.12-2': 02364 echo $OUTPUT->notification("Undefined Sequencing Request"); 02365 break; 02366 02367 case 'DB.1.1-1': 02368 echo $OUTPUT->notification("Cannot deliver a non-leaf activity"); 02369 break; 02370 case 'DB.1.1-2': 02371 echo $OUTPUT->notification("Nothing to deliver"); 02372 break; 02373 case 'DB.1.1-3': 02374 echo $OUTPUT->notification("Activity unavailable"); 02375 break; 02376 02377 case 'DB.2-1': 02378 echo $OUTPUT->notification("Identified activity is already active"); 02379 break; 02380 02381 } 02382 02383 } 02384 } 02385 02386 02387 02388 02389