Exemple #1
0
 /** Tests for attempt deleted event */
 public function test_attempt_deleted_event()
 {
     global $USER;
     $this->resetAfterTest();
     scorm_insert_track(2, $this->eventscorm->id, 1, 4, 'cmi.core.score.raw', 10);
     $sink = $this->redirectEvents();
     scorm_delete_attempt(2, $this->eventscorm, 4);
     $events = $sink->get_events();
     $sink->close();
     $event = reset($events);
     // Verify data.
     $this->assertCount(3, $events);
     $this->assertInstanceOf('\\mod_scorm\\event\\attempt_deleted', $event);
     $this->assertEquals($USER->id, $event->userid);
     $this->assertEquals(context_module::instance($this->eventcm->id), $event->get_context());
     $this->assertEquals(4, $event->other['attemptid']);
     $this->assertEquals(2, $event->relateduserid);
     $expected = array($this->eventcourse->id, 'scorm', 'delete attempts', 'report.php?id=' . $this->eventcm->id, 4, $this->eventcm->id);
     $this->assertEventLegacyLogData($expected, $events[0]);
     $this->assertEventContextNotUsed($event);
     // Test event validations.
     $this->setExpectedException('coding_exception');
     \mod_scorm\event\attempt_deleted::create(array('contextid' => 5, 'relateduserid' => 2));
     $this->fail('event \\mod_scorm\\event\\attempt_deleted is not validating events properly');
 }
Exemple #2
0
 private static function scorm_start_time($userid, $scormid, $scoid, $attempts, $starttime)
 {
     global $DB;
     if ($attempts == '') {
         $attempts = 1;
     }
     $data = array_values($DB->get_records_sql("SELECT id FROM mdl_scorm_scoes_track WHERE userid = " . $userid . " AND scormid = " . $scormid . " AND scoid = " . $scoid . " AND attempt = " . $attempts . " AND element LIKE 'x.start.time' ORDER BY id DESC"));
     //$res['scormid'] = $data[0]->id;
     if (!empty($data)) {
     } else {
         $id = scorm_insert_track($userid, $scormid, $scoid, $attempts, 'x.start.time', $starttime);
     }
 }
Exemple #3
0
    $index = 0;
    foreach ($objectives as $objective) {
        if (!empty($objective->minnormalizedmeasure)) {
            $userdata->{'cmi.scaled_passing_score'} = $objective->minnormalizedmeasure;
        }
        if (!empty($objective->objectiveid)) {
            $userdata->{'cmi.objectives.N'.$index.'.id'} = $objective->objectiveid;
            $index++;
        }
    }
}

header('Content-Type: text/javascript; charset=UTF-8');

$scorm->version = strtolower(clean_param($scorm->version, PARAM_SAFEDIR));   // Just to be safe.
if (file_exists($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'.js.php')) {
    include_once($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'.js.php');
} else {
    include_once($CFG->dirroot.'/mod/scorm/datamodels/scorm_12.js.php');
}
// Set the start time of this SCO.
scorm_insert_track($USER->id, $scorm->id, $scoid, $attempt, 'x.start.time', time());
?>


var errorCode = "0";
function underscore(str) {
    str = String(str).replace(/.N/g,".");
    return str.replace(/\./g,"__");
}
Exemple #4
0
 /**
  * Test get scorm sco tracks
  */
 public function test_mod_scorm_get_scorm_sco_tracks()
 {
     global $DB;
     $this->resetAfterTest(true);
     // Create users.
     $student = self::getDataGenerator()->create_user();
     $otherstudent = self::getDataGenerator()->create_user();
     $teacher = self::getDataGenerator()->create_user();
     // Set to the student user.
     self::setUser($student);
     // Create courses to add the modules.
     $course = self::getDataGenerator()->create_course();
     // First scorm.
     $record = new stdClass();
     $record->course = $course->id;
     $scorm = self::getDataGenerator()->create_module('scorm', $record);
     // Users enrolments.
     $studentrole = $DB->get_record('role', array('shortname' => 'student'));
     $teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
     $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
     $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
     // Create attempts.
     $scoes = scorm_get_scoes($scorm->id);
     $sco = array_shift($scoes);
     scorm_insert_track($student->id, $scorm->id, $sco->id, 1, 'cmi.core.lesson_status', 'completed');
     scorm_insert_track($student->id, $scorm->id, $sco->id, 1, 'cmi.core.score.raw', '80');
     scorm_insert_track($student->id, $scorm->id, $sco->id, 2, 'cmi.core.lesson_status', 'completed');
     $result = mod_scorm_external::get_scorm_sco_tracks($sco->id, $student->id, 1);
     $result = external_api::clean_returnvalue(mod_scorm_external::get_scorm_sco_tracks_returns(), $result);
     // 7 default elements + 2 custom ones.
     $this->assertCount(9, $result['data']['tracks']);
     $this->assertEquals(1, $result['data']['attempt']);
     $this->assertCount(0, $result['warnings']);
     // Find our tracking data.
     $found = 0;
     foreach ($result['data']['tracks'] as $userdata) {
         if ($userdata['element'] == 'cmi.core.lesson_status' and $userdata['value'] == 'completed') {
             $found++;
         }
         if ($userdata['element'] == 'cmi.core.score.raw' and $userdata['value'] == '80') {
             $found++;
         }
     }
     $this->assertEquals(2, $found);
     // Try invalid attempt.
     $result = mod_scorm_external::get_scorm_sco_tracks($sco->id, $student->id, 10);
     $result = external_api::clean_returnvalue(mod_scorm_external::get_scorm_sco_tracks_returns(), $result);
     $this->assertCount(0, $result['data']['tracks']);
     $this->assertEquals(10, $result['data']['attempt']);
     $this->assertCount(1, $result['warnings']);
     $this->assertEquals('notattempted', $result['warnings'][0]['warningcode']);
     // Capabilities check.
     try {
         mod_scorm_external::get_scorm_sco_tracks($sco->id, $otherstudent->id);
         $this->fail('Exception expected due to invalid instance id.');
     } catch (required_capability_exception $e) {
         $this->assertEquals('nopermissions', $e->errorcode);
     }
     self::setUser($teacher);
     // Ommit the attempt parameter, the function should calculate the last attempt.
     $result = mod_scorm_external::get_scorm_sco_tracks($sco->id, $student->id);
     $result = external_api::clean_returnvalue(mod_scorm_external::get_scorm_sco_tracks_returns(), $result);
     // 7 default elements + 1 custom one.
     $this->assertCount(8, $result['data']['tracks']);
     $this->assertEquals(2, $result['data']['attempt']);
     // Test invalid instance id.
     try {
         mod_scorm_external::get_scorm_sco_tracks(0, 1);
         $this->fail('Exception expected due to invalid instance id.');
     } catch (moodle_exception $e) {
         $this->assertEquals('cannotfindsco', $e->errorcode);
     }
     // Invalid user.
     try {
         mod_scorm_external::get_scorm_sco_tracks($sco->id, 0);
         $this->fail('Exception expected due to invalid instance id.');
     } catch (moodle_exception $e) {
         $this->assertEquals('invaliduser', $e->errorcode);
     }
 }
function scorm_seq_set($what, $scoid, $userid, $attempt = 0, $value = 'true')
{
    global $DB;
    $sco = scorm_get_sco($scoid);
    // Set passed activity to active or not.
    if ($value == false) {
        $DB->delete_records('scorm_scoes_track', array('scoid' => $scoid, 'userid' => $userid, 'attempt' => $attempt, 'element' => $what));
    } else {
        scorm_insert_track($userid, $sco->scorm, $sco->id, $attempt, $what, $value);
    }
    // Update grades in gradebook.
    $scorm = $DB->get_record('scorm', array('id' => $sco->scorm));
    scorm_update_grades($scorm, $userid, true);
}
Exemple #6
0
             if ($mode == 'browse' && $initlessonstatus == 'not attempted') {
                 $lessonstatus = 'browsed';
                 $id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, 'cmi.core.lesson_status', 'browsed');
             }
             if ($mode == 'normal') {
                 if ($sco = scorm_get_sco($scoid)) {
                     if (!empty($sco->mastery_score)) {
                         if (!empty($score)) {
                             if ($score >= $sco->mastery_score) {
                                 $lessonstatus = 'passed';
                             } else {
                                 $lessonstatus = 'failed';
                             }
                         }
                     }
                     $id = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, 'cmi.core.lesson_status', $lessonstatus);
                 }
             }
         }
         echo "error=0\r\nerror_text=Successful\r\n";
     } else {
         if ($status == 'Terminated') {
             echo "error=1\r\nerror_text=Terminated\r\n";
         } else {
             echo "error=1\r\nerror_text=Not Initialized\r\n";
         }
     }
     break;
 case 'putcomments':
     if ($status == 'Running') {
         echo "error=0\r\nerror_text=Successful\r\n";
Exemple #7
0
            }
        }
    }
}
//
// If no sco was found get the first of SCORM package
//
if (!isset($sco)) {
    $scoes = $DB->get_records_select('scorm_scoes', "scorm = ? AND launch <> ?", array($scorm->id, $DB->sql_empty()), 'id ASC');
    $sco = current($scoes);
}
if ($sco->scormtype == 'asset') {
    $attempt = scorm_get_last_attempt($scorm->id, $USER->id);
    $element = $scorm->version == 'scorm_13' || $scorm->version == 'SCORM_1.3' ? 'cmi.completion_status' : 'cmi.core.lesson_status';
    $value = 'completed';
    $result = scorm_insert_track($USER->id, $scorm->id, $sco->id, $attempt, $element, $value);
}
//
// Forge SCO URL
//
$connector = '';
$version = substr($scorm->version, 0, 4);
if (isset($sco->parameters) && !empty($sco->parameters) || $version == 'AICC') {
    if (stripos($sco->launch, '?') !== false) {
        $connector = '&';
    } else {
        $connector = '?';
    }
    if (isset($sco->parameters) && !empty($sco->parameters) && $sco->parameters[0] == '?') {
        $sco->parameters = substr($sco->parameters, 1);
    }
function JLMS_LoadSCOSCORM($option)
{
    global $JLMS_DB, $my, $Itemid;
    $JLMS_CONFIG =& JLMSFactory::getConfig();
    $id = intval(mosGetParam($_REQUEST, 'id', 0));
    $delayseconds = 20;
    // Delay time before sco launch, used to give time to browser to define API
    $delayseconds_nojs = 2;
    // if API were defined earlier than timer is passed - SCO will be launched
    if ($id) {
        $query = "SELECT * FROM #__lms_n_scorm WHERE id = {$id}";
        $JLMS_DB->SetQuery($query);
        $scorm = $JLMS_DB->LoadObject();
        if (is_object($scorm)) {
            $scoid = intval(mosGetParam($_REQUEST, 'scoid', 0));
            if (!empty($scoid)) {
                //
                // Direct SCO request
                //
                if ($sco = scorm_get_sco($scoid)) {
                    // (DEN) check if this $scoid from our SCORM !!!!
                    if ($sco->launch == '') {
                        // Search for the next launchable sco
                        $query = "SELECT * FROM #__lms_n_scorm_scoes WHERE scorm = {$scorm->id} AND launch <> '' AND id > {$sco->id} ORDER BY id ASC";
                        $JLMS_DB->SetQuery($query);
                        $scoes = $JLMS_DB->LoadObjectList();
                        //if ($scoes = get_records_select('scorm_scoes','scorm='.$scorm->id." AND launch<>'' AND id>".$sco->id,'id ASC')) {
                        if (!empty($scoes)) {
                            $sco = current($scoes);
                        }
                    }
                }
            }
            //
            // If no sco was found get the first of SCORM package
            //
            if (!isset($sco)) {
                $query = "SELECT * FROM #__lms_n_scorm_scoes WHERE scorm = {$scorm->id} AND launch <> '' ORDER BY id ASC";
                $JLMS_DB->SetQuery($query);
                $scoes = $JLMS_DB->LoadObjectList();
                //$scoes = get_records_select('scorm_scoes','scorm='.$scorm->id." AND launch<>''",'id ASC');
                $sco = current($scoes);
            }
            if (!empty($sco)) {
                if ($sco->scormtype == 'asset') {
                    $attempt = scorm_get_last_attempt($scorm->id, $my->id);
                    $element = $scorm->version == 'scorm_13' ? 'cmi.completion_status' : 'cmi.core.lesson_status';
                    $value = 'completed';
                    $result = scorm_insert_track($my->id, $scorm->id, $sco->id, $attempt, $element, $value);
                }
            }
            //
            // Forge SCO URL
            //
            $connector = '';
            $version = substr($scorm->version, 0, 4);
            if (isset($sco->parameters) && !empty($sco->parameters) || $version == 'AICC') {
                /**
                 * 06.10.2007 (DEN) "''." - is added for compatibility with Joomla compatibility :)) library compat.php50x.php (on line 105 in PHP 4.4.7 there was a notice)
                 */
                if (stripos('' . $sco->launch, '?') !== false) {
                    $connector = '&';
                } else {
                    $connector = '?';
                }
                if (isset($sco->parameters) && !empty($sco->parameters) && $sco->parameters[0] == '?') {
                    $sco->parameters = substr($sco->parameters, 1);
                }
            }
            if ($version == 'AICC') {
                if (isset($sco->parameters) && !empty($sco->parameters)) {
                    $sco->parameters = '&' . $sco->parameters;
                }
                //$launcher = $sco->launch.$connector.'aicc_sid='.$my->id.'&aicc_url='.$CFG->wwwroot.'/mod/scorm/aicc.php'.$sco->parameters;
                $launcher = $sco->launch . $connector . 'aicc_sid=' . $my->id . '&aicc_url=' . $JLMS_CONFIG->get('live_site') . "/index.php?option={$option}&Itemid={$Itemid}&task=aicc_task&course_id={$course_id}" . $sco->parameters;
                // (DEN) check this URL /\ !!!!!!!!!
            } else {
                if (isset($sco->parameters) && !empty($sco->parameters)) {
                    $launcher = $sco->launch . $connector . $sco->parameters;
                } else {
                    $launcher = $sco->launch;
                }
            }
            $query = "SELECT * FROM #__lms_scorm_packages WHERE id = {$scorm->scorm_package}";
            $JLMS_DB->SetQuery($query);
            $scorm_ref = $JLMS_DB->LoadObject();
            //$reference = $CFG->dataroot.'/'.$courseid.'/'.$reference;
            //$row->reference = _JOOMLMS_SCORM_FOLDER_PATH . "/" . $scorm_ref->package_srv_name;
            $reference_folder = $JLMS_CONFIG->get('live_site') . "/" . _JOOMLMS_SCORM_PLAYER . "/" . $scorm_ref->folder_srv_name;
            //$reference_folder = _JOOMLMS_SCORM_FOLDER_PATH . "/" . $scorm_ref->folder_srv_name;
            // (DEN) we don't use external links nor repositry (but maybe...maybe...)
            /*if (scorm_external_link($sco->launch)) {
            			// Remote learning activity
            			$result = $launcher;
            		} else if ($scorm->reference[0] == '#') {
            			// Repository
            			require_once($repositoryconfigfile);
            			$result = $CFG->repositorywebroot.substr($scorm->reference,1).'/'.$sco->launch;
            		} else {*/
            if (true) {
                // (DEN) we don't use external packages
                /*if ((basename($scorm->reference) == 'imsmanifest.xml') && scorm_external_link($scorm->reference)) {
                			// Remote manifest
                			$result = dirname($scorm->reference).'/'.$launcher;
                		} else {*/
                if (true) {
                    // Moodle internal package/manifest or remote (auto-imported) package
                    //if (basename($scorm->reference) == 'imsmanifest.xml') {
                    if (basename($reference_folder) == 'imsmanifest.xml') {
                        //$basedir = dirname($scorm->reference);
                        $basedir = dirname($reference_folder);
                    } else {
                        $basedir = $reference_folder;
                        //$CFG->moddata.'/scorm/'.$scorm->id;
                    }
                    /*if ($CFG->slasharguments) {
                    			$result = $CFG->wwwroot.'/file.php/'.$scorm->course.'/'.$basedir.'/'.$launcher;
                    		} else {
                    			$result = $CFG->wwwroot.'/file.php?file=/'.$scorm->course.'/'.$basedir.'/'.$launcher;
                    		}*/
                    $result = $reference_folder . '/' . $launcher;
                    // determine the name of the API variable, which are we looking for
                    $LMS_api = $scorm->version == 'scorm_12' || $scorm->version == 'SCORM_1.2' || empty($scorm->version) ? 'API' : 'API_1484_11';
                    if (isset($sco->scormtype) && strtolower($sco->scormtype) == 'asset') {
                        $delayseconds = 2;
                        // if resource is 'asset' - we don't need SCORM API
                    }
                    ?>
<html>
    <head>
        <title>LoadSCO</title>
        <script type="text/javascript">
        //<![CDATA[
		var delaySeconds = <?php 
                    echo $delayseconds;
                    ?>

		function findscormAPI(win) {
			var findAPITries = 0;
			while ((win.<?php 
                    echo $LMS_api;
                    ?>
 == null) && (win.parent != null) && (win.parent != win)) {
				findAPITries++;
				if (findAPITries > 7) { // we don't have more than 7 nested window objects....
					return null;
				}
				win = win.parent;
			}
			return win.<?php 
                    echo $LMS_api;
                    ?>
;
		}

		function getscormAPI() {
			var theAPI = findscormAPI(window);
			if ((theAPI == null) && (window.opener != null) && (typeof(window.opener) != "undefined")) {
				theAPI = findscormAPI(window.opener);
			}
			if (theAPI == null) {
				return null;
			}
			return theAPI;
		}

		function try_redirect() {
			if (getscormAPI() == null) {
				delaySeconds = delaySeconds - 1;
				if (delaySeconds < 0) {
					setTimeout('do_window_redirect();',1000);
				} else {
					setTimeout('try_redirect();',1000);
				}
			} else {
				setTimeout('do_window_redirect();',1000);
			}
		}
		function do_window_redirect() {
			document.location = "<?php 
                    echo $result;
                    ?>
";
		}
        //]]>
        </script>
        <noscript>
            <meta http-equiv="refresh" content="<?php 
                    echo $delayseconds_nojs;
                    ?>
;url=<?php 
                    echo $result;
                    ?>
" />
        </noscript> 
    </head>
    <body onload="try_redirect();">
        <br /><br /><center><img src="<?php 
                    echo $JLMS_CONFIG->get('live_site');
                    ?>
/components/com_joomla_lms/lms_images/loading.gif" height="32" width="32" border="0" alt="loading" /></center>
    </body>
</html>
<?php 
                }
            }
        }
    }
    die;
}
Exemple #9
0
function scorm_content_delivery_environment($seq, $userid)
{
    $act = $seq->currentactivity;
    if (scorm_seq_is('active', $act->id, $userid)) {
        $seq->exception = 'DB.2-1';
        return $seq;
    }
    $track = get_record('scorm_scoes_track', 'scoid', $act->id, 'userid', $userid, 'element', 'suspendedactivity');
    if ($track != null) {
        $seq = scorm_clear_suspended_activity($seq->delivery, $seq);
    }
    $seq = scorm_terminate_descendent_attempts($seq->delivery, $userid, $seq);
    $ancestors = scorm_get_ancestors($seq->delivery);
    $arrpath = array_reverse($ancestors);
    array_push($arrpath, $seq->delivery);
    foreach ($arrpath as $activity) {
        if (!scorm_seq_is('active', $activity->id, $userid)) {
            if (!isset($activity->tracked) || $activity->tracked == 1) {
                if (!scorm_seq_is('suspended', $activity->id, $userid)) {
                    $r = get_record('scorm_scoes_track', 'scoid', $activity->id, 'userid', $userid, 'element', 'activityattemptcount');
                    $r->value = $r->value + 1;
                    update_record('scorm_scoes_track', $r);
                    if ($r->value == 1) {
                        scorm_seq_set('activityprogressstatus', $activity->id, $userid, 'true');
                    }
                    scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectiveprogressstatus', 'false');
                    scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectivesatisfiedstatus', 'false');
                    scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectivemeasurestatus', 'false');
                    scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'objectivenormalizedmeasure', 0.0);
                    scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptprogressstatus', 'false');
                    scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptcompletionstatus', 'false');
                    scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptabsoluteduration', 0.0);
                    scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptexperiencedduration', 0.0);
                    scorm_insert_track($userid, $activity->scorm, $activity->id, 0, 'attemptcompletionamount', 0.0);
                }
            }
            scorm_seq_set('active', $activity->id, $userid, 'true');
        }
    }
    $seq->delivery = $seq->currentactivity;
    scorm_seq_set('suspendedactivity', $activity->id, $userid, 'false');
    //ONCE THE DELIVERY BEGINS (How should I check that?)
    if (isset($activity->tracked) || $activity->tracked == 0) {
        //How should I track the info and what should I do to not record the information for the activity during delivery?
        $atabsdur = get_record('scorm_scoes_track', 'scoid', $activity->id, 'userid', $userid, 'element', 'attemptabsoluteduration');
        $atexpdur = get_record('scorm_scoes_track', 'scoid', $activity->id, 'userid', $userid, 'element', 'attemptexperiencedduration');
    }
    return $seq;
}
Exemple #10
0
 /**
  * Saves a SCORM tracking record.
  * It will overwrite any existing tracking data for this attempt.
  * Validation should be performed before running the function to ensure the user will not lose any existing attempt data.
  *
  * @param int $scoid the SCO id
  * @param string $attempt the attempt number
  * @param array $tracks the track records to be stored
  * @return array warnings and the scoes data
  * @throws moodle_exception
  * @since Moodle 3.0
  */
 public static function insert_scorm_tracks($scoid, $attempt, $tracks)
 {
     global $USER, $DB;
     $params = self::validate_parameters(self::insert_scorm_tracks_parameters(), array('scoid' => $scoid, 'attempt' => $attempt, 'tracks' => $tracks));
     $trackids = array();
     $warnings = array();
     $sco = scorm_get_sco($params['scoid'], SCO_ONLY);
     if (!$sco) {
         throw new moodle_exception('cannotfindsco', 'scorm');
     }
     $scorm = $DB->get_record('scorm', array('id' => $sco->scorm), '*', MUST_EXIST);
     $cm = get_coursemodule_from_instance('scorm', $scorm->id);
     $context = context_module::instance($cm->id);
     self::validate_context($context);
     // Check settings / permissions to view the SCORM.
     require_capability('mod/scorm:savetrack', $context);
     // Check settings / permissions to view the SCORM.
     scorm_require_available($scorm);
     foreach ($params['tracks'] as $track) {
         $element = $track['element'];
         $value = $track['value'];
         $trackid = scorm_insert_track($USER->id, $scorm->id, $sco->id, $params['attempt'], $element, $value, $scorm->forcecompleted);
         if ($trackid) {
             $trackids[] = $trackid;
         } else {
             $warnings[] = array('item' => 'scorm', 'itemid' => $scorm->id, 'warningcode' => 1, 'message' => 'Element: ' . $element . ' was not saved');
         }
     }
     $result = array();
     $result['trackids'] = $trackids;
     $result['warnings'] = $warnings;
     return $result;
 }
Exemple #11
0
            error("Course Module ID was incorrect");
        }
    } else {
        error('A required parameter is missing');
    }
}
require_login($course->id, false, $cm);
if (confirm_sesskey() && !empty($scoid)) {
    $result = true;
    $request = null;
    if (has_capability('mod/scorm:savetrack', get_context_instance(CONTEXT_MODULE, $cm->id))) {
        foreach ($_POST as $element => $value) {
            $element = str_replace('__', '.', $element);
            if (substr($element, 0, 3) == 'cmi') {
                $netelement = preg_replace('/\\.N(\\d+)\\./', "\\.\$1\\.", $element);
                $result = scorm_insert_track($USER->id, $scorm->id, $scoid, $attempt, $netelement, $value) && $result;
            }
            if (substr($element, 0, 15) == 'adl.nav.request') {
                // SCORM 2004 Sequencing Request
                require_once 'datamodels/sequencinglib.php';
                $search = array('@continue@', '@previous@', '@\\{target=(\\S+)\\}choice@', '@exit@', '@exitAll@', '@abandon@', '@abandonAll@');
                $replace = array('continue_', 'previous_', '\\1', 'exit_', 'exitall_', 'abandon_', 'abandonall');
                $action = preg_replace($search, $replace, $value);
                if ($action != $value) {
                    // Evaluating navigation request
                    $valid = scorm_seq_overall($scoid, $USER->id, $action, $attempt);
                    $valid = 'true';
                    // Set valid request
                    $search = array('@continue@', '@previous@', '@\\{target=(\\S+)\\}choice@');
                    $replace = array('true', 'true', 'true');
                    $matched = preg_replace($search, $replace, $value);
        }
    } else {
        print_error('missingparameter');
    }
}
$PAGE->set_url('/mod/scorm/datamodel.php', array('scoid' => $scoid, 'attempt' => $attempt, 'id' => $cm->id));
require_login($course, false, $cm);
if (confirm_sesskey() && !empty($scoid)) {
    $result = true;
    $request = null;
    if (has_capability('mod/scorm:savetrack', get_context_instance(CONTEXT_MODULE, $cm->id))) {
        foreach (data_submitted() as $element => $value) {
            $element = str_replace('__', '.', $element);
            if (substr($element, 0, 3) == 'cmi') {
                $netelement = preg_replace('/\\.N(\\d+)\\./', "\\.\$1\\.", $element);
                $result = scorm_insert_track($USER->id, $scorm->id, $scoid, $attempt, $element, $value, $scorm->forcecompleted) && $result;
            }
            if (substr($element, 0, 15) == 'adl.nav.request') {
                // SCORM 2004 Sequencing Request
                require_once $CFG->dirroot . '/mod/scorm/datamodels/sequencinglib.php';
                $search = array('@continue@', '@previous@', '@\\{target=(\\S+)\\}choice@', '@exit@', '@exitAll@', '@abandon@', '@abandonAll@');
                $replace = array('continue_', 'previous_', '\\1', 'exit_', 'exitall_', 'abandon_', 'abandonall');
                $action = preg_replace($search, $replace, $value);
                if ($action != $value) {
                    // Evaluating navigation request
                    $valid = scorm_seq_overall($scoid, $USER->id, $action, $attempt);
                    $valid = 'true';
                    // Set valid request
                    $search = array('@continue@', '@previous@', '@\\{target=(\\S+)\\}choice@');
                    $replace = array('true', 'true', 'true');
                    $matched = preg_replace($search, $replace, $value);
function scorm_seq_set($what, $scoid, $userid, $attempt = 0, $value = 'true')
{
    /// set passed activity to active or not
    if ($value == false) {
        delete_record('scorm_scoes_track', 'scoid', $scoid, 'userid', $userid, 'element', $what);
    } else {
        $sco = scorm_get_sco($scoid);
        scorm_insert_track($userid, $sco->scorm, $sco->id, 0, $what, $value);
    }
}
function scorm_tcapi_store_statement($params, $statementObject) {
	global $CFG, $USER, $DB, $SESSION;
	if (isset($params['actor']) && isset($params['actor']->moodle_user))
		$userid = $params['actor']->moodle_user;
	else
		$userid = $USER->id;
	if (isset($params['moodle_mod_id']))
		$scoid = $params['moodle_mod_id'];
	else
		throw new invalid_parameter_exception('Module id not provided.');
	require_once($CFG->dirroot.'/mod/scorm/locallib.php');
	if (($sco = scorm_get_sco($scoid)) && ($attempt = scorm_get_last_attempt($sco->scorm, $userid)))
	{
		$usertrack = scorm_get_tracks($scoid, $userid, $attempt);
		
	    // if the activity is considered complete, only update the time if it doesn't yet exist
		$attempt_complete = ($usertrack && (($usertrack->status == 'completed') || ($usertrack->status == 'passed') || ($usertrack->status == 'failed')));
			
		$statement = $statementObject->statement;
		$statementRow = $statementObject->statementRow;
		// check that the incoming statement refers to the sco identifier
		if (isset($statement->activity)) {
			$sco_activity = $statement->activity;
			// TODO: Add support for interaction tracks for child results reporting.
			//if (!empty($statement->activity->grouping_id) && ($lrs_activity = $DB->get_record_select('tcapi_activity','id = ?',array($statement->activity->grouping_id))))
				//$sco_activity = $lrs_activity;
			if ($sco->identifier == $sco_activity->activity_id) {
				// check for existing cmi.core.lesson_status
				// set default to 'incomplete'
				// check statement->verb and set cmi.core.lesson_status as appropriate
				$cmiCoreLessonStatus = (empty($usertrack->status) || $usertrack->status == 'notattempted') ? 'incomplete' : $usertrack->status;
				if (in_array(strtolower($statementRow->verb),array('completed','passed','mastered','failed'))) {
					$cmiCoreLessonStatus = strtolower($statementRow->verb);
					// Indicates activity status is complete
					$complStatus = ($cmiCoreLessonStatus !== 'failed') ? 'completed' : 'incomplete';
					if (!$attempt_complete)
						scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.completion_status', $complStatus);
					// Create/update track for cmi.core.lesson_status 
					if (!$attempt_complete && in_array($cmiCoreLessonStatus,array('passed','failed','completed','incomplete')))
						scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.core.lesson_status', $cmiCoreLessonStatus);
					if (!$attempt_complete && in_array($cmiCoreLessonStatus,array('passed','failed')))
						scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.success_status', $cmiCoreLessonStatus);
					elseif (!isset($usertrack->{'cmi.success_status'}))
						scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.success_status', 'unknown');
					// check if any result was reported
					if (isset($statementObject->resultRow)) {
						$result = $statementObject->resultRow;
						// if a duration was reported, add to any existing total_time
						if (isset($result->duration))
						{
							if ($usertrack->total_time == '00:00:00')
								$total_time = $result->duration;
							elseif (!$attempt_complete)
								$total_time = scorm_tcapi_add_time($result->duration, $usertrack->total_time);
							if (isset($total_time))
								scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.core.total_time', $total_time);
						}
						
						if (isset($result->score) && !$attempt_complete)
						{
							$score = json_decode($result->score);
							if (isset($score->raw))
								scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.core.score.raw', $score->raw);
							if (isset($score->min))
								scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.core.score.min', $score->min);
							if (isset($score->max))
								scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.core.score.max', $score->max);
							// if scaled is provided but no raw, calculate the raw as we need it for SCORM grades
							// try to use the min/max if available. if not, use 0/100
							if (isset($score->scaled)) {
								if (!isset($score->raw)) {
									$scoremin = (isset($score->min)) ? $score->min : 0;
									$scoremax = (isset($score->max)) ? $score->max : 100;
									$score->raw = ($score->scaled*($scoremax-$scoremin))+$scoremin;
									scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.core.score.raw', $score->raw);
									if (!isset($score->min))
										scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.core.score.min', $scoremin);
									if (!isset($score->max))
										scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.core.score.max', $scoremax);
								}
								scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.score.scaled', $score->scaled);								
							}
						}
						
					}
				}
				if ($attempt_complete)
					return $statementObject->statementId;
					
				// set cmi.core.exit to suspend if status is incomplete, else remove the track entry
				if ($cmiCoreLessonStatus == 'incomplete')
					scorm_insert_track($userid, $sco->scorm, $scoid, $attempt, 'cmi.core.exit', 'suspend');
				elseif ($track = $DB->get_record('scorm_scoes_track', array('userid'=>$userid, 'scormid'=>$sco->scorm, 'scoid'=>$scoid, 'attempt'=>$attempt, 'element'=>'cmi.core.exit')))
					$DB->delete_records_select('scorm_scoes_track', 'id = ?', array($track->id));
			}
		}
	}
	else 
		throw new invalid_parameter_exception('Parameters invalid or Scorm/Sco not found.');
	
	
	return $statementObject->statementId;	
}