PageRenderTime 68ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/mod/scorm/datamodels/sequencinglib.php

https://bitbucket.org/ceu/moodle_demo
PHP | 2342 lines | 1912 code | 376 blank | 54 comment | 586 complexity | 0769f4a8e30cd86cf3264ceeeb550593 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php // $Id: sequencinglib.php,v 1.17.2.2 2010/06/23 23:13:19 danmarsden Exp $
  2. require ($CFG->dirroot.'/mod/scorm/datamodels/scormlib.php');
  3. function scorm_seq_evaluate($scoid,$usertracks) {
  4. return true;
  5. }
  6. function scorm_seq_overall ($scoid,$userid,$request,$attempt) {
  7. $seq = scorm_seq_navigation($scoid,$userid,$request,$attempt);
  8. if ($seq->navigation) {
  9. if ($seq->termination != null) {
  10. $seq = scorm_seq_termination($scoid,$userid,$seq);
  11. }
  12. if ($seq->sequencing != null) {
  13. $seq = scorm_seq_sequencing($scoid,$userid,$seq);
  14. if($seq->sequencing == 'exit'){//return the control to the LTS
  15. return 'true';
  16. }
  17. }
  18. if ($seq->delivery != null) {
  19. $seq = scorm_sequencing_delivery($scoid,$userid,$seq);
  20. $seq = scorm_content_delivery_environment ($seq,$userid);
  21. }
  22. }
  23. if ($seq->exception != null) {
  24. $seq = scorm_sequencing_exception($seq);
  25. }
  26. return 'true';
  27. }
  28. function scorm_seq_navigation ($scoid,$userid,$request,$attempt=0) {
  29. /// Sequencing structure
  30. $seq = new stdClass();
  31. $seq->currentactivity = scorm_get_sco($scoid);
  32. $seq->traversaldir = null;
  33. $seq->nextactivity = null;
  34. $seq->deliveryvalid = null;
  35. $seq->attempt = $attempt;
  36. $seq->identifiedactivity = null;
  37. $seq->delivery = null;
  38. $seq->deliverable = false;
  39. $seq->active = scorm_seq_is('active',$scoid,$userid);
  40. $seq->suspended = scorm_seq_is('suspended',$scoid,$userid);
  41. $seq->navigation = null;
  42. $seq->termination = null;
  43. $seq->sequencing = null;
  44. $seq->target = null;
  45. $seq->endsession = null;
  46. $seq->exception = null;
  47. $seq->reachable = true;
  48. $seq->prevact = true;
  49. switch ($request) {
  50. case 'start_':
  51. if (empty($seq->currentactivity)) {
  52. $seq->navigation = true;
  53. $seq->sequencing = 'start';
  54. } else {
  55. $seq->exception = 'NB.2.1-1'; /// Sequencing session already begun
  56. }
  57. break;
  58. case 'resumeall_':
  59. if (empty($seq->currentactivity)) {
  60. if ($track = get_record('scorm_scoes_track','scoid',$scoid,'userid',$userid,'element','suspendedactivity')) {//I think it's suspend instead of suspendedactivity
  61. $seq->navigation = true;
  62. $seq->sequencing = 'resumeall';
  63. } else {
  64. $seq->exception = 'NB.2.1-3'; /// No suspended activity found
  65. }
  66. } else {
  67. $seq->exception = 'NB.2.1-1'; /// Sequencing session already begun
  68. }
  69. break;
  70. case 'continue_':
  71. case 'previous_':
  72. if (!empty($seq->currentactivity)) {
  73. $sco = $seq->currentactivity;
  74. if ($sco->parent != '/') {
  75. if ($parentsco = scorm_get_parent($sco)) {
  76. if (isset($parentsco->flow) && ($parentsco->flow == true)) {//I think it's parentsco
  77. // Current activity is active !
  78. if (scorm_seq_is('active',$sco->id,$userid)) {
  79. if ($request == 'continue_') {
  80. $seq->navigation = true;
  81. $seq->termination = 'exit';
  82. $seq->sequencing = 'continue';
  83. } else {
  84. if (!isset($parentsco->forwardonly) || ($parentsco->forwardonly == false)) {
  85. $seq->navigation = true;
  86. $seq->termination = 'exit';
  87. $seq->sequencing = 'previous';
  88. } else {
  89. $seq->exception = 'NB.2.1-5'; /// Violates control mode
  90. }
  91. }
  92. }
  93. }
  94. }
  95. }
  96. } else {
  97. $seq->exception = 'NB.2.1-2'; /// Current activity not defined
  98. }
  99. break;
  100. case 'forward_':
  101. case 'backward_':
  102. $seq->exception = 'NB.2.1-7' ; /// None to be done, behavior not defined
  103. break;
  104. case 'exit_':
  105. case 'abandon_':
  106. if (!empty($seq->currentactivity)) {
  107. // Current activity is active !
  108. $seq->navigation = true;
  109. $seq->termination = substr($request,0,-1);
  110. $seq->sequencing = 'exit';
  111. } else {
  112. $seq->exception = 'NB.2.1-2'; /// Current activity not defined
  113. }
  114. case 'exitall_':
  115. case 'abandonall_':
  116. case 'suspendall_':
  117. if (!empty($seq->currentactivity)) {
  118. $seq->navigation = true;
  119. $seq->termination = substr($request,0,-1);
  120. $seq->sequencing = 'exit';
  121. } else {
  122. $seq->exception = 'NB.2.1-2'; /// Current activity not defined
  123. }
  124. break;
  125. default: /// {target=<STRING>}choice
  126. if ($targetsco = get_record('scorm_scoes','scorm',$sco->scorm,'identifier',$request)) {
  127. if ($targetsco->parent != '/') {
  128. $seq->target = $request;
  129. } else {
  130. if ($parentsco = scorm_get_parent($targetsco)) {
  131. if (!isset($parentsco->choice) || ($parent->choice == true)) {
  132. $seq->target = $request;
  133. }
  134. }
  135. }
  136. if ($seq->target != null) {
  137. if (empty($seq->currentactivity)) {
  138. $seq->navigation = true;
  139. $seq->sequencing = 'choice';
  140. } else {
  141. if (!$sco = scorm_get_sco($scoid)) {
  142. return $seq;
  143. }
  144. if ($sco->parent != $target->parent) {
  145. $ancestors = scorm_get_ancestors($sco);
  146. $commonpos = scorm_find_common_ancestor($ancestors,$targetsco);
  147. if ($commonpos !== false) {
  148. if ($activitypath = array_slice($ancestors,0,$commonpos)) {
  149. foreach ($activitypath as $activity) {
  150. if (scorm_seq_is('active',$activity->id,$userid) && (isset($activity->choiceexit) && ($activity->choiceexit == false))) {
  151. $seq->navigation = false;
  152. $seq->termination = null;
  153. $seq->sequencing = null;
  154. $seq->target = null;
  155. $seq->exception = 'NB.2.1-8'; /// Violates control mode
  156. return $seq;
  157. }
  158. }
  159. } else {
  160. $seq->navigation = false;
  161. $seq->termination = null;
  162. $seq->sequencing = null;
  163. $seq->target = null;
  164. $seq->exception = 'NB.2.1-9';
  165. }
  166. }
  167. }
  168. // Current activity is active !
  169. $seq->navigation = true;
  170. $seq->sequencing = 'choice';
  171. }
  172. } else {
  173. $seq->exception = 'NB.2.1-10'; /// Violates control mode
  174. }
  175. } else {
  176. $seq->exception = 'NB.2.1-11'; /// Target activity does not exists
  177. }
  178. break;
  179. }
  180. return $seq;
  181. }
  182. function scorm_seq_termination ($seq,$userid) {
  183. if (empty($seq->currentactivity)) {
  184. $seq->termination = false;
  185. $seq->exception = 'TB.2.3-1';
  186. return $seq;
  187. }
  188. $sco = $seq->currentactivity;
  189. if ((($seq->termination == 'exit') || ($seq->termination == 'abandon')) && !$seq->active) {
  190. $seq->termination = false;
  191. $seq->exception = 'TB.2.3-2';
  192. return $seq;
  193. }
  194. switch ($seq->termination) {
  195. case 'exit':
  196. scorm_seq_end_attempt($sco,$userid,$seq);
  197. $seq = scorm_seq_exit_action_rules($seq,$userid);
  198. do {
  199. $exit = false;// I think this is false. Originally this was true
  200. $seq = scorm_seq_post_cond_rules($seq,$userid);
  201. if ($seq->termination == 'exitparent') {
  202. if ($sco->parent != '/') {
  203. $sco = scorm_get_parent($sco);
  204. $seq->currentactivity = $sco;
  205. $seq->active = scorm_seq_is('active',$sco->id,$userid);
  206. scorm_seq_end_attempt($sco,$userid,$seq);
  207. $exit = true;//I think it's true. Originally this was false
  208. } else {
  209. $seq->termination = false;
  210. $seq->exception = 'TB.2.3-4';
  211. return $seq;
  212. }
  213. }
  214. } while (($exit == false) && ($seq->termination == 'exit'));
  215. if ($seq->termination == 'exit') {
  216. $seq->termination = true;
  217. return $seq;
  218. }
  219. case 'exitall':
  220. if ($seq->active) {
  221. scorm_seq_end_attempt($sco,$userid,$seq);
  222. }
  223. /// Terminate Descendent Attempts Process
  224. if ($ancestors = scorm_get_ancestors($sco)) {
  225. foreach ($ancestors as $ancestor) {
  226. scorm_seq_end_attempt($ancestor,$userid,$seq);
  227. $seq->currentactivity = $ancestor;
  228. }
  229. }
  230. $seq->active = scorm_seq_is('active',$seq->currentactivity->id,$userid);
  231. $seq->termination = true;
  232. $seq->sequencing = exit;
  233. break;
  234. case 'suspendall':
  235. if (($seq->active) || ($seq->suspended)) {
  236. scorm_seq_set('suspended',$sco->id,$userid);
  237. } else {
  238. if ($sco->parent != '/') {
  239. $parentsco = scorm_get_parent($sco);
  240. scorm_seq_set('suspended',$parentsco->id,$userid);
  241. } else {
  242. $seq->termination = false;
  243. $seq->exception = 'TB.2.3-3';
  244. // return $seq;
  245. }
  246. }
  247. if ($ancestors = scorm_get_ancestors($sco)) {
  248. foreach ($ancestors as $ancestor) {
  249. scorm_seq_set('active',$ancestor->id,$userid,false);
  250. scorm_seq_set('suspended',$ancestor->id,$userid);
  251. $seq->currentactivity = $ancestor;
  252. }
  253. $seq->termination = true;
  254. $seq->sequencing = 'exit';
  255. } else {
  256. $seq->termination = false;
  257. $seq->exception = 'TB.2.3-5';
  258. }
  259. break;
  260. case 'abandon':
  261. scorm_seq_set('active',$sco->id,$userid,false);
  262. $seq->active = null;
  263. $seq->termination = true;
  264. break;
  265. case 'abandonall':
  266. if ($ancestors = scorm_get_ancestors($sco)) {
  267. foreach ($ancestors as $ancestor) {
  268. scorm_seq_set('active',$ancestor->id,$userid,false);
  269. $seq->currentactivity = $ancestor;
  270. }
  271. $seq->termination = true;
  272. $seq->sequencing = 'exit';
  273. } else {
  274. $seq->termination = false;
  275. $seq->exception = 'TB.2.3-6';
  276. }
  277. break;
  278. default:
  279. $seq->termination = false;
  280. $seq->exception = 'TB.2.3-7';
  281. break;
  282. }
  283. return $seq;
  284. }
  285. function scorm_seq_end_attempt($sco,$userid,$seq) {
  286. if (scorm_is_leaf($sco)) {
  287. if (!isset($sco->tracked) || ($sco->tracked == 1)) {
  288. if (!scorm_seq_is('suspended',$sco->id,$userid)) {
  289. if (!isset($sco->completionsetbycontent) || ($sco->completionsetbycontent == 0)) {
  290. if (!scorm_seq_is('attemptprogressstatus',$sco->id,$userid,$seq->attempt)) {
  291. // if (!scorm_seq_is('attemptprogressstatus',$sco->id,$userid)) {
  292. scorm_seq_set('attemptprogressstatus',$sco->id,$userid);
  293. scorm_seq_set('attemptcompletionstatus',$sco->id,$userid);
  294. }
  295. }
  296. if (!isset($sco->objectivesetbycontent) || ($sco->objectivesetbycontent == 0)) {
  297. if ($objectives = get_records('scorm_seq_objective','scoid',$sco->id)) {
  298. foreach ($objectives as $objective) {
  299. if ($objective->primaryobj) {
  300. //if (!scorm_seq_objective_progress_status($sco,$userid,$objective)) {
  301. if (!scorm_seq_is('objectiveprogressstatus',$sco->id,$userid)) {
  302. scorm_seq_set('objectiveprogressstatus',$sco->id,$userid);
  303. scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid);
  304. }
  305. }
  306. }
  307. }
  308. }
  309. }
  310. }
  311. } else {
  312. if ($children = scorm_get_children($sco)) {
  313. $suspended = false;
  314. foreach ($children as $child) {
  315. if (scorm_seq_is('suspended',$child,$userid)) {
  316. $suspended = true;
  317. break;
  318. }
  319. }
  320. if ($suspended) {
  321. scorm_seq_set('suspended',$sco,$userid);
  322. } else {
  323. scorm_seq_set('suspended',$sco,$userid,false);
  324. }
  325. }
  326. }
  327. scorm_seq_set('active',$sco,$userid,0,false);
  328. scorm_seq_overall_rollup($sco,$userid);
  329. }
  330. function scorm_seq_is($what, $scoid, $userid, $attempt=0) {
  331. /// Check if passed activity $what is active
  332. $active = false;
  333. if ($track = get_record('scorm_scoes_track','scoid',$scoid,'userid',$userid,'attempt',$attempt,'element',$what)) {
  334. $active = true;
  335. }
  336. return $active;
  337. }
  338. function scorm_seq_set($what, $scoid, $userid, $attempt=0, $value='true') {
  339. $sco = scorm_get_sco($scoid);
  340. /// set passed activity to active or not
  341. if ($value == false) {
  342. delete_record('scorm_scoes_track','scoid',$scoid,'userid',$userid,'attempt',$attempt,'element',$what);
  343. } else {
  344. scorm_insert_track($userid, $sco->scorm, $sco->id, 0, $what, $value);
  345. }
  346. // update grades in gradebook
  347. $scorm = get_record('scorm', 'id', $sco->scorm);
  348. scorm_update_grades($scorm, $userid, true);
  349. }
  350. function scorm_seq_exit_action_rules($seq,$userid) {
  351. $sco = $seq->currentactivity;
  352. $ancestors = scorm_get_ancestors($sco);
  353. $exittarget = null;
  354. foreach (array_reverse($ancestors) as $ancestor) {
  355. if (scorm_seq_rules_check($ancestor,'exit') != null) {
  356. $exittarget = $ancestor;
  357. break;
  358. }
  359. }
  360. if ($exittarget != null) {
  361. $commons = array_slice($ancestors,0,scorm_find_common_ancestor($ancestors,$exittarget));
  362. /// Terminate Descendent Attempts Process
  363. if ($commons) {
  364. foreach ($commons as $ancestor) {
  365. scorm_seq_end_attempt($ancestor,$userid,$seq->attempt);
  366. $seq->currentactivity = $ancestor;
  367. }
  368. }
  369. }
  370. return $seq;
  371. }
  372. function scorm_seq_post_cond_rules($seq,$userid) {
  373. $sco = $seq->currentactivity;
  374. if (!$seq->suspended) {
  375. if ($action = scorm_seq_rules_check($sco,'post') != null) {
  376. switch($action) {
  377. case 'retry':
  378. case 'continue':
  379. case 'previous':
  380. $seq->sequencing = $action;
  381. break;
  382. case 'exitparent':
  383. case 'exitall':
  384. $seq->termination = $action;
  385. break;
  386. case 'retryall':
  387. $seq->termination = 'exitall';
  388. $seq->sequencing = 'retry';
  389. break;
  390. }
  391. }
  392. }
  393. return $seq;
  394. }
  395. function scorm_seq_rules_check ($sco, $action){
  396. $act = null;
  397. if($rules = get_records('scorm_seq_ruleconds','scoid',$sco->id,'action',$action)){
  398. foreach ($rules as $rule){
  399. if($act = scorm_seq_rule_check($sco,$rule)){
  400. return $act;
  401. }
  402. }
  403. }
  404. return $act;
  405. }
  406. function scorm_seq_rule_check ($sco, $rule){
  407. $bag = Array();
  408. $cond = '';
  409. $ruleconds = get_records('scorm_seq_rulecond','scoid',$sco->id,'ruleconditionsid',$rule->id);
  410. foreach ($ruleconds as $rulecond){
  411. if ($rulecond->operator = 'not') {
  412. if ($rulecond->cond != 'unknown' ){
  413. $rulecond->cond = 'not'.$rulecond;
  414. }
  415. }
  416. $bag [$rule->id] = $rulecond->cond;
  417. }
  418. if (empty($bag)){
  419. $cond = 'unknown';
  420. return $cond;
  421. }
  422. $size= sizeof($bag);
  423. $i=0;
  424. if ($rule->conditioncombination = 'all'){
  425. foreach ($bag as $con){
  426. $cond = $cond.' and '.$con;
  427. }
  428. }
  429. else{
  430. foreach ($bag as $con){
  431. $cond = $cond.' or '.$con;
  432. }
  433. }
  434. return $cond;
  435. }
  436. function scorm_seq_overall_rollup($sco,$userid){//Carlos
  437. if ($ancestors = scorm_get_ancestors($sco)) {
  438. foreach ($ancestors as $ancestor) {
  439. if(!scorm_is_leaf($ancestor)){
  440. scorm_seq_measure_rollup($sco,$userid);
  441. }
  442. scorm_seq_objective_rollup($sco,$userid);
  443. scorm_seq_activity_progress_rollup($sco,$userid);
  444. }
  445. }
  446. }
  447. /* 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*/
  448. function scorm_seq_measure_rollup($sco,$userid){
  449. $totalmeasure = 0; //Check if there is something similar in the database
  450. $valid = false;//Same as in the last line
  451. $countedmeasures = 0;//Same too
  452. $targetobjective = null;
  453. $readable = true;//to check if status and measure weight are readable
  454. $objectives = get_records('scorm_seq_objective','scoid',$sco->id);
  455. foreach ($objective as $objective){
  456. if ($objective->primaryobj == true){//Objective contributes to rollup I'm using primaryobj field, but not
  457. $targetobjective = $objective;
  458. break;
  459. }
  460. }
  461. if ($targetobjective != null){
  462. $children = scorm_get_children($sco);
  463. foreach ($children as $child){
  464. $child = scorm_get_sco ($child);
  465. if (!isset($child->tracked) || ($child->tracked == 1)){
  466. $rolledupobjective = null;// we set the rolled up activity to undefined
  467. $objectives = get_records('scorm_seq_objective','scoid',$child->id);
  468. foreach ($objective as $objective){
  469. if ($objective->primaryobj == true){//Objective contributes to rollup I'm using primaryobj field, but not
  470. $rolledupobjective = $objective;
  471. break;
  472. }
  473. }
  474. if ($rolledupobjective != null){
  475. $child = scorm_get_sco($child->id);
  476. $countedmeasures = $countedmeasures + ($child->measureweight);
  477. if (!scorm_seq_is('objectivemeasurestatus',$sco->id,$userid)) {
  478. $normalizedmeasure = get_record('scorm_scoes_track','scoid',$child->id,'userid',$userid,'element','objectivenormalizedmeasure');
  479. $totalmeasure = $totalmeasure + (($normalizedmeasure->value) * ($child->measureweight));
  480. $valid = true;
  481. }
  482. }
  483. }
  484. }
  485. if(!$valid){
  486. scorm_seq_set('objectivemeasurestatus',$sco->id,$userid,false);
  487. }
  488. else{
  489. if($countedmeasures>0){
  490. scorm_seq_set('objectivemeasurestatus',$sco->id,$userid);
  491. $val=$totalmeasure/$countedmeasure;
  492. scorm_seq_set('objectivenormalizedmeasure',$sco->id,$userid,$val);
  493. }
  494. else{
  495. scorm_seq_set('objectivemeasurestatus',$sco->id,$userid,false);
  496. }
  497. }
  498. }
  499. }
  500. function scorm_seq_objective_rollup($sco,$userid){
  501. scorm_seq_objective_rollup_measure($sco,$userid);
  502. scorm_seq_objective_rollup_rules($sco,$userid);
  503. scorm_seq_objective_rollup_default($sco,$userid);
  504. /*
  505. if($targetobjective->satisfiedbymeasure){
  506. scorm_seq_objective_rollup_measure($sco,$userid);
  507. }
  508. else{
  509. if ((scorm_seq_rollup_rule_check($sco,$userid,'incomplete'))|| (scorm_seq_rollup_rule_check($sco,$userid,'completed'))){
  510. scorm_seq_objective_rollup_rules($sco,$userid);
  511. }
  512. else{
  513. $rolluprules = get_record('scorm_seq_rolluprule','scoid',$sco->id,'userid',$userid);
  514. foreach($rolluprules as $rolluprule){
  515. $rollupruleconds = get_records('scorm_seq_rolluprulecond','rollupruleid',$rolluprule->id);
  516. foreach($rollupruleconds as $rolluprulecond){
  517. switch ($rolluprulecond->cond!='satisfied' && $rolluprulecond->cond!='completed' && $rolluprulecond->cond!='attempted'){
  518. scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid, false);
  519. break;
  520. }
  521. }
  522. }
  523. }
  524. */
  525. }
  526. function scorm_seq_objective_rollup_measure($sco,$userid){
  527. $targetobjective = null;
  528. $objectives = get_records('scorm_seq_objective','scoid',$sco->id);
  529. foreach ($objectives as $objective){
  530. if ($objective->primaryobj == true){
  531. $targetobjective = $objective;
  532. break;
  533. }
  534. }
  535. if ($targetobjective != null){
  536. if($targetobjective->satisfiedbymeasure){
  537. if (!scorm_seq_is('objectiveprogressstatus',$sco->id,$userid)) {
  538. scorm_seq_set('objectiveprogressstatus',$sco->id,$userid,false);
  539. }
  540. else{
  541. if (scorm_seq_is('active',$sco->id,$userid)) {
  542. $isactive = true;
  543. }
  544. else{
  545. $isactive = false;
  546. }
  547. $normalizedmeasure = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','objectivenormalizedmeasure');
  548. $sco = scorm_get_sco ($sco->id);
  549. if (!$isactive || ($isactive && (!isset($sco->measuresatisfactionifactive) || $sco->measuresatisfactionifactive == true))){
  550. if($normalizedmeasure->value >= $targetobjective->minnormalizedmeasure){
  551. scorm_seq_set('objectiveprogressstatus',$sco->id,$userid);
  552. scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid);
  553. }
  554. else{
  555. scorm_seq_set('objectiveprogressstatus',$sco->id,$userid);
  556. scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid,false);
  557. }
  558. }
  559. else{
  560. scorm_seq_set('objectiveprogressstatus',$sco->id,$userid,false);
  561. }
  562. }
  563. }
  564. }
  565. }
  566. function scorm_seq_objective_rollup_default($sco,$userid){
  567. if (!(scorm_seq_rollup_rule_check($sco,$userid,'incomplete')) && !(scorm_seq_rollup_rule_check($sco,$userid,'completed'))){
  568. $rolluprules = get_record('scorm_seq_rolluprule','scoid',$sco->id,'userid',$userid);
  569. foreach($rolluprules as $rolluprule){
  570. $rollupruleconds = get_records('scorm_seq_rolluprulecond','rollupruleid',$rolluprule->id);
  571. foreach($rollupruleconds as $rolluprulecond){
  572. if ($rolluprulecond->cond!='satisfied' && $rolluprulecond->cond!='completed' && $rolluprulecond->cond!='attempted'){
  573. scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid, false);
  574. break;
  575. }
  576. }
  577. }
  578. }
  579. }
  580. function scorm_seq_objective_rollup_rules($sco,$userid){
  581. $targetobjective = null;
  582. $objectives = get_records('scorm_seq_objective','scoid',$sco->id);
  583. foreach ($objective as $objective){
  584. if ($objective->primaryobj == true){//Objective contributes to rollup I'm using primaryobj field, but not
  585. $targetobjective = $objective;
  586. break;
  587. }
  588. }
  589. if ($targetobjective != null){
  590. if(scorm_seq_rollup_rule_check($sco,$userid,'notsatisfied')){//with not satisfied rollup for the activity
  591. scorm_seq_set('objectiveprogressstatus',$sco->id,$userid);
  592. scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid,false);
  593. }
  594. if(scorm_seq_rollup_rule_check($sco,$userid,'satisfied')){//with satisfied rollup for the activity
  595. scorm_seq_set('objectiveprogressstatus',$sco->id,$userid);
  596. scorm_seq_set('objectivesatisfiedstatus',$sco->id,$userid);
  597. }
  598. }
  599. }
  600. function scorm_seq_activity_progress_rollup ($sco, $userid){
  601. if(scorm_seq_rollup_rule_check($sco,$userid,'incomplete')){
  602. //incomplete rollup action
  603. scorm_seq_set('attemptcompletionstatus',$sco->id,$userid,false,$seq->attempt);
  604. scorm_seq_set('attemptprogressstatus',$sco->id,$userid,true,$seq->attempt);
  605. }
  606. if(scorm_seq_rollup_rule_check($sco,$userid,'completed')){
  607. //incomplete rollup action
  608. scorm_seq_set('attemptcompletionstatus',$sco->id,true,$userid);
  609. scorm_seq_set('attemptprogressstatus',$sco->id,true,$userid);
  610. }
  611. }
  612. function scorm_seq_rollup_rule_check ($sco,$userid,$action){
  613. if($rolluprules = get_record('scorm_seq_rolluprule','scoid',$sco->id,'userid',$userid,'action',$action)){
  614. $childrenbag = Array ();
  615. $children = scorm_get_children ($sco);
  616. foreach($rolluprules as $rolluprule){
  617. foreach ($children as $child){
  618. /*$tracked = get_records('scorm_scoes_track','scoid',$child->id,'userid',$userid);
  619. if($tracked && $tracked->attemp != 0){*/
  620. $child = scorm_get_sco ($child);
  621. if (!isset($child->tracked) || ($child->tracked == 1)){
  622. if(scorm_seq_check_child ($child,$action,$userid)){
  623. $rollupruleconds = get_records('scorm_seq_rolluprulecond','rollupruleid',$rolluprule->id);
  624. $evaluate = scorm_seq_evaluate_rollupcond($child,$rolluprule->conditioncombination,$rollupruleconds,$userid);
  625. if ($evaluate=='unknown'){
  626. array_push($childrenbag,'unknown');
  627. }
  628. else{
  629. if($evaluate == true){
  630. array_push($childrenbag,true);
  631. }
  632. else{
  633. array_push($childrenbag,false);
  634. }
  635. }
  636. }
  637. }
  638. }
  639. $change = false;
  640. switch ($rolluprule->childactivityset){
  641. case 'all':
  642. if((array_search(false,$childrenbag)===false)&&(array_search('unknown',$childrenbag)===false)){//I think I can use this condition instead equivalent to OR
  643. $change = true;
  644. }
  645. break;
  646. case 'any':
  647. if(array_search(true,$childrenbag)!==false){//I think I can use this condition instead equivalent to OR
  648. $change = true;
  649. }
  650. break;
  651. case 'none':
  652. if((array_search(true,$childrenbag)===false)&&(array_search('unknown',$childrenbag)===false)){//I think I can use this condition instead equivalent to OR
  653. $change = true;
  654. }
  655. break;
  656. case 'atleastcount':
  657. foreach ($childrenbag as $itm){//I think I can use this condition instead equivalent to OR
  658. $cont = 0;
  659. if($itm === true){
  660. $cont++;
  661. }
  662. if($cont >= $roullprule->minimumcount){
  663. $change = true;
  664. }
  665. }
  666. break;
  667. case 'atleastcount':
  668. foreach ($childrenbag as $itm){//I think I can use this condition instead equivalent to OR
  669. $cont = 0;
  670. if($itm === true){
  671. $cont++;
  672. }
  673. if($cont >= $roullprule->minimumcount){
  674. $change = true;
  675. }
  676. }
  677. break;
  678. case 'atleastpercent':
  679. foreach ($childrenbag as $itm){//I think I can use this condition instead equivalent to OR
  680. $cont = 0;
  681. if($itm === true){
  682. $cont++;
  683. }
  684. if(($cont/sizeof($childrenbag)) >= $roullprule->minimumcount){
  685. $change = true;
  686. }
  687. }
  688. break;
  689. }
  690. if ($change==true){
  691. return true;
  692. }
  693. }
  694. }
  695. return false;
  696. }
  697. function scorm_seq_evaluate_rollupcond($sco,$conditioncombination,$rollupruleconds,$userid){
  698. $bag = Array();
  699. $con = "";
  700. $val = false;
  701. $unk = false;
  702. foreach($rollupruleconds as $rolluprulecond){
  703. $condit = scorm_evaluate_cond($rolluprulecond,$sco,$userid);
  704. if($rule->operator=='not'){// If operator is not, negate the condition
  705. if ($rule->cond != 'unknown'){
  706. if ($condit){
  707. $condit = false;
  708. }
  709. else{
  710. $condit = true;
  711. }
  712. }
  713. else{
  714. $condit = 'unknown';
  715. }
  716. array_push($childrenbag,$condit);
  717. }
  718. }
  719. if (empty($bag)){
  720. return 'unknown';
  721. }
  722. else{
  723. $i = 0;
  724. foreach ($bag as $b){
  725. if ($rolluprule->conditioncombination == 'all'){
  726. $val = true;
  727. if($b == 'unknown'){
  728. $unk = true;
  729. }
  730. if($b === false){
  731. return false;
  732. }
  733. }
  734. else{
  735. $val = false;
  736. if($b == 'unknown'){
  737. $unk = true;
  738. }
  739. if($b === true){
  740. return true;
  741. }
  742. }
  743. }
  744. }
  745. if ($unk){
  746. return 'unknown';
  747. }
  748. return $val;
  749. }
  750. function scorm_evaluate_condition ($rolluprulecond,$sco,$userid){
  751. $res = false;
  752. switch ($rolluprulecond->cond){
  753. case 'satisfied':
  754. if($r=get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','objectivesatisfiedstatus')){
  755. if($r->value == true){
  756. if ($r=get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','objectiveprogressstatus')){
  757. if($r->value == true){
  758. $res= true;
  759. }
  760. }
  761. }
  762. }
  763. break;
  764. case 'objectiveStatusKnown':
  765. if ($r=get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','objectiveprogressstatus')){
  766. if($r->value == true){
  767. $res= true;
  768. }
  769. }
  770. break;
  771. case 'objectiveMeasureKnown':
  772. if ($r = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','objectivemeasurestatus')){
  773. if($r->value == true){
  774. $res = true;
  775. }
  776. }
  777. break;
  778. case 'completed':
  779. if ($r = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','attemptcompletionstatus')){
  780. if($r->value){
  781. if ($r = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','attemptprogressstatus')){
  782. if($r->value){
  783. $res = true;
  784. }
  785. }
  786. }
  787. }
  788. break;
  789. case 'attempted':
  790. if ($r = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','activityprogressstatus')){
  791. if($r->value){
  792. if ($r = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','activityattemptcount')){
  793. if($r->value > 0){
  794. $res = true;
  795. }
  796. }
  797. }
  798. }
  799. break;
  800. case 'attemptLimitExceeded':
  801. if ($r = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','activityprogressstatus')){
  802. if($r->value){
  803. if ($r = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','limitconditionattemptlimitcontrol')){
  804. if($r->value){
  805. if ($r = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','activityattemptcount') && $r2 = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','limitconditionattemptlimit') ){
  806. if($r->value >= $r2->value){
  807. $res = true;
  808. }
  809. }
  810. }
  811. }
  812. }
  813. }
  814. break;
  815. case 'activityProgressKnown':
  816. if ($r = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','activityprogressstatus')){
  817. if($r->value){
  818. if ($r = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','attemptprogressstatus')){
  819. if($r->value){
  820. $res = true;
  821. }
  822. }
  823. }
  824. }
  825. break;
  826. }
  827. return $res;
  828. }
  829. function scorm_seq_check_child ($sco, $action, $userid){
  830. $included = false;
  831. $sco=scorm_get_sco($sco->id);
  832. $r = get_record('scorm_scoes_track','scoid',$sco->id,'userid',$userid,'element','activityattemptcount');
  833. if ($action == 'satisfied' || $action == 'notsatisfied'){
  834. if (!$sco->rollupobjectivesatisfied){
  835. $included = true;
  836. if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifnotsuspended') || ($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifnotsuspended')){
  837. if (!scorm_seq_is('activityprogressstatus',$sco->id,$userid) || ((($r->value)>0)&& !scorm_seq_is('suspended',$sco->id,$userid))){
  838. $included = false;
  839. }
  840. }
  841. else{
  842. if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifattempted') || ($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifattempted')){
  843. if (!scorm_seq_is('activityprogressstatus',$sco->id,$userid) || (($r->value) == 0)){
  844. $included = false;
  845. }
  846. }
  847. else{
  848. if (($action == 'satisfied' && $sco->requiredforsatisfied == 'ifnotskipped') || ($action == 'notsatisfied' && $sco->requiredfornotsatisfied == 'ifnotskipped')){
  849. $rulch = scorm_seq_rules_check($sco, 'skip');
  850. if ($rulch != null){
  851. $included = false;
  852. }
  853. }
  854. }
  855. }
  856. }
  857. }
  858. if ($action == 'completed' || $action == 'incomplete'){
  859. if (!$sco->rollupprogresscompletion){
  860. $included = true;
  861. if (($action == 'completed' && $sco->requiredforcompleted == 'ifnotsuspended') || ($action == 'incomplete' && $sco->requiredforincomplete == 'ifnotsuspended')){
  862. if (!scorm_seq_is('activityprogressstatus',$sco->id,$userid) || ( (($r->value)>0)&& !scorm_seq_is('suspended',$sco->id,$userid))){
  863. $included = false;
  864. }
  865. }
  866. else{
  867. if (($action == 'completed' && $sco->requiredforcompleted == 'ifattempted') || ($action == 'incomplete' && $sco->requiredforincomplete == 'ifattempted')){
  868. if (!scorm_seq_is('activityprogressstatus',$sco->id,$userid) || (($r->value)==0)){
  869. $included = false;
  870. }
  871. }
  872. else{
  873. if (($action == 'completed' && $sco->requiredforsatisfied == 'ifnotskipped') || ($action == 'incomplete' && $sco->requiredfornotsatisfied == 'ifnotskipped')){
  874. $rulch = scorm_seq_rules_check($sco, 'skip');
  875. if ($rulch != null){
  876. $included = false;
  877. }
  878. }
  879. }
  880. }
  881. }
  882. }
  883. return $included;
  884. }
  885. function scorm_seq_sequencing ($scoid,$userid,$seq) {
  886. switch ($seq->sequencing) {
  887. case 'start':
  888. $seq = scorm_seq_start_sequencing($sco,$userid,$seq); //We'll see the parameters we have to send, this should update delivery and end
  889. $seq->sequencing = true;
  890. break;
  891. case 'resumeall':
  892. $seq = scorm_seq_resume_sequencing($sco,$userid,$seq); //We'll see the parameters we have to send, this should update delivery and end
  893. $seq->sequencing = true;
  894. break;
  895. case 'exit':
  896. $seq = scorm_seq_exit_sequencing($sco,$userid,$seq); //We'll see the parameters we have to send, this should update delivery and end
  897. $seq->sequencing = true;
  898. break;
  899. case 'retry':
  900. $seq = scorm_seq_retry_sequencing($sco,$userid,$seq); //We'll see the parameters we have to send, this should update delivery and end
  901. $seq->sequencing = true;
  902. break;
  903. case 'previous':
  904. $seq = scorm_seq_previous_sequencing($sco,$userid,$seq);// We'll see the parameters we have to send, this should update delivery and end
  905. $seq->sequencing = true;
  906. break;
  907. case 'choice':
  908. $seq = scorm_seq_choice_sequencing($sco,$userid,$seq);// We'll see the parameters we have to send, this should update delivery and end
  909. $seq->sequencing = true;
  910. break;
  911. }
  912. if ($seq->exception != null){
  913. $seq->sequencing = false;
  914. return $seq;
  915. }
  916. $seq->sequencing= true;
  917. return $seq;
  918. }
  919. function scorm_seq_start_sequencing($scoid,$userid,$seq){
  920. if (!empty($seq->currentactivity)) {
  921. $seq->delivery = null;
  922. $seq->exception = 'SB.2.5-1';
  923. return $seq;
  924. }
  925. $sco = get_record('scorm_scoes','scoid',$scoid,'userid',$userid);
  926. if (($sco->parent == '/') && scorm_is_leaf($sco)) {//if the activity is the root and is leaf
  927. $seq->delivery = $sco;
  928. }
  929. else{
  930. $ancestors = scorm_get_ancestors($sco);
  931. $ancestorsroot = array_reverse($ancestors);
  932. $res = scorm_seq_flow($ancestorsroot[0],'forward',$seq,true,$userid);
  933. if($res){
  934. return $res;
  935. }
  936. else{
  937. //return end and exception
  938. }
  939. }
  940. }
  941. function scorm_seq_resume_all_sequencing($scoid,$userid,$seq){
  942. if (!empty($seq->currentactivity)){
  943. $seq->delivery = null;
  944. $seq->exception = 'SB.2.6-1';
  945. return $seq;
  946. }
  947. $track = get_record('scorm_scoes_track','scoid',$scoid,'userid',$userid,'element','suspendedactivity');
  948. if (!$track) {
  949. $seq->delivery = null;
  950. $seq->exception = 'SB.2.6-2';
  951. return $seq;
  952. }
  953. $seq->delivery = get_record('scorm_scoes','scoid',$scoid,'userid',$userid);//we assign the sco to the delivery
  954. }
  955. function scorm_seq_continue_sequencing($scoid,$userid,$seq){
  956. if (empty($seq->currentactivity)) {
  957. $seq->delivery = null;
  958. $seq->exception = 'SB.2.7-1';
  959. return $seq;
  960. }
  961. $currentact= $seq->currentactivity;
  962. if ($currentact->parent != '/') {//if the activity is the root and is leaf
  963. $parent = scorm_get_parent ($currentact);
  964. if (!isset($parent->flow) || ($parent->flow == false)) {
  965. $seq->delivery = null;
  966. $seq->exception = 'SB.2.7-2';
  967. return $seq;
  968. }
  969. $res = scorm_seq_flow($currentact,'forward',$seq,false,$userid);
  970. if($res){
  971. return $res;
  972. }
  973. else{
  974. //return end and exception
  975. }
  976. }
  977. }
  978. function scorm_seq_previous_sequencing($scoid,$userid,$seq){
  979. if (empty($seq->currentactivity)) {
  980. $seq->delivery = null;
  981. $seq->exception = 'SB.2.8-1';
  982. return $seq;
  983. }
  984. $currentact= $seq->currentactivity;
  985. if ($currentact->parent != '/') {//if the activity is the root and is leaf
  986. $parent = scorm_get_parent ($activity);
  987. if (!isset($parent->flow) || ($parent->flow == false)) {
  988. $seq->delivery = null;
  989. $seq->exception = 'SB.2.8-2';
  990. return $seq;
  991. }
  992. $res = scorm_seq_flow($currentact,'backward',$seq,false,$userid);
  993. if($res){
  994. return $res;
  995. }
  996. else{
  997. //return end and exception
  998. }
  999. }
  1000. }
  1001. function scorm_seq_exit_sequencing($scoid,$userid,$seq){
  1002. if (empty($seq->currentactivity)) {
  1003. $seq->delivery = null;
  1004. $seq->exception = 'SB.2.11-1';
  1005. return $seq;
  1006. }
  1007. if ($seq->active){
  1008. $seq->endsession = false;
  1009. $seq->exception = 'SB.2.11-2';
  1010. return $seq;
  1011. }
  1012. $currentact= $seq->currentactivity;
  1013. if ($currentact->parent == '/'){
  1014. $seq->endsession = true;
  1015. return $seq;
  1016. }
  1017. $seq->endsession = false;
  1018. return $seq;
  1019. }
  1020. function scorm_seq_retry_sequencing($scoid,$userid,$seq){
  1021. if (empty($seq->currentactivity)) {
  1022. $seq->delivery = null;
  1023. $seq->exception = 'SB.2.10-1';
  1024. return $seq;
  1025. }
  1026. if ($seq->active || $seq->suspended){
  1027. $seq->delivery = null;
  1028. $seq->exception = 'SB.2.10-2';
  1029. return $seq;
  1030. }
  1031. if (!scorm_is_leaf($seq->currentactivity)){
  1032. $res = scorm_seq_flow($seq->currentactivity,'forward',$seq,true,$userid);
  1033. if($res != null){
  1034. return $res;
  1035. //return deliver
  1036. }
  1037. else{
  1038. $seq->delivery = null;
  1039. $seq->exception = 'SB.2.10-3';
  1040. return $seq;
  1041. }
  1042. }
  1043. else{
  1044. $seq->delivery = $seq->currentactivity;
  1045. return $seq;
  1046. }
  1047. }
  1048. function scorm_seq_flow ($candidate,$direction,$seq,$childrenflag,$userid){
  1049. //$PREVDIRECTION NOT DEFINED YET
  1050. $activity=$candidate;
  1051. $deliverable=false;
  1052. $previdirection = null;
  1053. $seq = scorm_seq_flow_tree_traversal ($activity,$direction,$childrenflag,$prevdirection,$seq,$userid);
  1054. if($seq->identifiedactivity == null){//if identifies
  1055. $seq->identifiedactivity = $candidate;
  1056. $seq->deliverable = false;
  1057. return $seq;
  1058. }
  1059. else{
  1060. $activity = $seq->identifiedactivity;
  1061. $seq = scorm_seq_flow_activity_traversal($activity,$userid,$direction,$childrenflag,$prevdirection,$seq,$userid);//
  1062. return $seq;
  1063. }
  1064. }
  1065. 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
  1066. $activity = scorm_get_sco ($activity);
  1067. $parent = scorm_get_parent ($activity);
  1068. if (!isset($parent->flow) || ($parent->flow == false)) {
  1069. $seq->deliverable = false;
  1070. $seq->exception = 'SB.2.2-1';
  1071. $seq->nextactivity = $activity;
  1072. return $seq;
  1073. }
  1074. $rulch = scorm_seq_rules_check($sco, 'skipped');
  1075. if ($rulch != null){
  1076. $seq = scorm_seq_flow_tree_traversal ($activity, $direction, false, $prevdirection, $seq,$userid);//endsession and exception
  1077. if ($seq->identifiedactivity == null){
  1078. $seq->deliverable = false;
  1079. $seq->nextactivity = $activity;
  1080. return $seq;
  1081. }
  1082. else{
  1083. if ($prevdirection = 'backward' && $seq->traversaldir == 'backward'){
  1084. $seq = scorm_seq_flow_tree_traversal ($activity,$direction,false,null,$seq,$userid);
  1085. $seq = scorm_seq_flow_activity($seq->identifiedactivity, $userid, $direction, $childrenflag, $prevdirection, $seq,$userid);
  1086. }
  1087. else{
  1088. $seq = scorm_seq_flow_tree_traversal ($activity,$direction,false,null,$seq,$userid);
  1089. $seq = scorm_seq_flow_activity($seq->identifiedactivity, $userid, $direction, $childrenflag, $prevdirection, $seq,$userid);
  1090. }
  1091. return $seq;
  1092. }
  1093. }
  1094. $ch=scorm_check_activity ($activity,$userid);
  1095. if ($ch){
  1096. $seq->deliverable = false;
  1097. $seq->exception = 'SB.2.2-2';
  1098. $seq->nextactivity = $activity;
  1099. return $seq;
  1100. }
  1101. if (!scorm_is_leaf($activity)){
  1102. $seq = scorm_seq_flow_tree_traversal ($activity,$direction,true,null,$seq,$userid);
  1103. if ($seq->identifiedactivity == null){
  1104. $seq->deliverable = false;
  1105. $seq->nextactivity = $activity;
  1106. return $seq;
  1107. }
  1108. else{
  1109. if($direction == 'backward' && $seq->traversaldir == 'forward'){
  1110. $seq = scorm_seq_flow_activity($seq->identifiedactivity, $userid, 'forward', $childrenflag, 'backward', $seq,$userid);
  1111. }
  1112. else{
  1113. scorm_seq_flow_activity($seq->identifiedactivity, $userid, $direction, $childrenflag, null, $seq,$userid);
  1114. }
  1115. return $seq;
  1116. }
  1117. }
  1118. $seq->deliverable = true;
  1119. $seq->nextactivity = $activity;
  1120. return $seq;
  1121. }
  1122. function scorm_seq_flow_tree_traversal ($activity,$direction,$childrenflag,$prevdirection,$seq,$userid){
  1123. $revdirection = false;
  1124. $parent = scorm_get_parent ($activity);
  1125. $children = scorm_get_available_children ($parent);
  1126. $siz = sizeof ($children);
  1127. if (($prevdirection != null && $prevdirection == 'backward') && ($children[$siz-1]->id == $activity->id)){
  1128. $direction = 'backward';
  1129. $children[0] = $activity;
  1130. $revdirection = true;
  1131. }
  1132. if($direction = 'forward'){
  1133. $ancestors = scorm_get_ancestors($activity);
  1134. $ancestorsroot = array_reverse($ancestors);
  1135. $preorder = scorm_get_preorder ($ancestorsroot);
  1136. $siz= sizeof ($preorder);
  1137. if (($activity->id == $preorder[$siz-1]->id) || (($activity->parent == '/') && !($childrenflag))){
  1138. scorm_seq_terminate_descent($ancestorsroot,$userid);
  1139. $seq->endsession = true;
  1140. $seq->nextactivity = null;
  1141. return $seq;
  1142. }
  1143. if (scorm_is_leaf ($activity) || !$childrenflag){
  1144. if ($children[$siz-1]->id == $activity->id){
  1145. $seq = scorm_seq_flow_tree_traversal ($parent, $direction, false, null, $seq,$userid);
  1146. // I think it's not necessary to do a return in here
  1147. }
  1148. else{
  1149. $parent = scorm_get_parent($activity);
  1150. $children = scorm_get_available_children($parent);
  1151. $seq->traversaldir = $direction;
  1152. $sib = scorm_get_siblings($activity);
  1153. $pos = array_search($sib, $activity);
  1154. if ($pos !== false) {
  1155. if ($pos != sizeof ($sib)){
  1156. $seq->nextactivity = $sib [$pos+1];
  1157. return $seq;
  1158. }
  1159. else{
  1160. $ch = scorm_get_children($sib[0]);
  1161. $seq->nextactivity = $ch[0];
  1162. return $seq;
  1163. }
  1164. }
  1165. }
  1166. }
  1167. else{
  1168. if (!empty ($children)){
  1169. $seq->traversaldir = $direction;
  1170. $seq->nextactivity = $children[0];
  1171. return $seq;
  1172. }
  1173. else{
  1174. $seq->traversaldir = null;
  1175. $seq->nextactivity = $children[0];
  1176. $seq->exception = 'SB.2.1-2';
  1177. return $seq;
  1178. }
  1179. }
  1180. }
  1181. if($direction = 'backward'){
  1182. if ($activity->parent == '/'){
  1183. $seq->traversaldir = null;
  1184. $seq->nextactivity = null;
  1185. $seq->exception = 'SB.2.1-3';
  1186. return $seq;
  1187. }
  1188. if (scorm_is_leaf ($activity) || !$childrenflag){
  1189. if (!$revdirection){
  1190. if (isset($parent->forwardonly) && ($parent->forwardonly == true)) {
  1191. $seq->traversaldir = null;
  1192. $seq->nextactivity = null;
  1193. $seq->exception = 'SB.2.1-4';
  1194. return $seq;
  1195. }
  1196. }
  1197. if ($children[0]->id == $activity->id){
  1198. $seq = scorm_seq_flow_tree_traversal ($parent, 'backward', false, null, $seq);
  1199. return $seq;
  1200. }
  1201. else{
  1202. $ancestors = scorm_get_ancestors($activity);
  1203. $ancestorsroot = array_reverse ($ancestors);
  1204. $preorder = scorm_get_preorder ($ancestorsroot);
  1205. $pos = array_search($preorder, $children[$siz]);
  1206. $preord = array_slice($preorder, 0, $pos-1);
  1207. $revpreorder = array_reverse($preord);
  1208. $position = array_search($revpreorder, $activity);
  1209. $seq->nextactivity = $revpreorder[$pos+1];
  1210. $seq->traversaldir = $direction;
  1211. return $seq;
  1212. }
  1213. }
  1214. else{
  1215. if (!empty($children)){
  1216. $activity = scorm_get_sco($activity->id);
  1217. if (isset($parent->flow) && ($parent->flow == true)) {
  1218. $children = scorm_get_children ($activity);
  1219. $seq->traversaldir = 'forward';
  1220. $seq->nextactivity = $children[0];
  1221. return $seq;
  1222. }
  1223. else{
  1224. $children = scorm_get_children ($activity);
  1225. $seq->traversaldir = 'backward';
  1226. $seq->nextactivity = $children[sizeof($children)-1];
  1227. return $seq;
  1228. }
  1229. }
  1230. else{
  1231. $seq->traversaldir = null;
  1232. $seq->nextactivity = null;
  1233. $seq->exception = 'SB.2.1-2';
  1234. return $seq;
  1235. }
  1236. }
  1237. }
  1238. }
  1239. function scorm_check_activity ($activity,$userid){
  1240. $act = scorm_seq_rules_check($activity,'disabled');
  1241. if ($act != null){
  1242. return true;
  1243. }
  1244. if(scorm_limit_cond_check ($activity,$userid)){
  1245. return true;
  1246. }
  1247. return false;
  1248. }
  1249. function scorm_limit_cond_check ($activity,$userid){
  1250. if (isset($activity->tracked) && ($activity->tracked == 0)){
  1251. return false;
  1252. }
  1253. if (scorm_seq_is('active',$activity->id,$userid) || scorm_seq_is('suspended',$activity->id,$userid)){
  1254. return false;
  1255. }
  1256. if (!isset($activity->limitcontrol) || ($activity->limitcontrol == 1)){
  1257. $r = get_record('scorm_scoes_track','scoid',$activity->id,'userid',$userid,'element','activityattemptcount');
  1258. if (scorm_seq_is('activityprogressstatus',$activity->id,$userid) && ($r->value >=$activity->limitattempt)){
  1259. return true;
  1260. }
  1261. }
  1262. if (!isset($activity->limitabsdurcontrol) || ($activity->limitabsdurcontrol == 1)){
  1263. $r = get_record('scorm_scoes_track','scoid',$activity->id,'userid',$userid,'element','activityabsoluteduration');
  1264. if (scorm_seq_is('activityprogressstatus',$activity->id,$userid) && ($r->value >=$activity->limitabsduration)){
  1265. return true;
  1266. }
  1267. }
  1268. if (!isset($activity->limitexpdurcontrol) || ($activity->limitexpdurcontrol == 1)){
  1269. $r = get_record('scorm_scoes_track','scoid',$activity->id,'userid',$userid,'element','activityexperiencedduration');
  1270. if (scorm_seq_is('activityprogressstatus',$activity->id,$userid) && ($r->value >=$activity->limitexpduration)){
  1271. return true;
  1272. }
  1273. }
  1274. if (!isset($activity->limitattabsdurcontrol) || ($activity->limitattabsdurcontrol == 1)){
  1275. $r = get_record('scorm_scoes_track','scoid',$activity->id,'userid',$userid,'element','attemptabsoluteduration');
  1276. if (scorm_seq_is('activityprogressstatus',$activity->id,$userid) && ($r->value >=$activity->limitattabsduration)){
  1277. return true;
  1278. }
  1279. }
  1280. if (!isset($activity->limitattexpdurcontrol) || ($activity->limitattexpdurcontrol == 1)){
  1281. $r = get_record('scorm_scoes_track','scoid',$activity->id,'userid',$userid,'element','attemptexperiencedduration');
  1282. if

Large files files are truncated, but you can click here to view the full file