function scorm_grade_user($scorm, $userid) { // ensure we dont grade user beyond $scorm->maxattempt settings $lastattempt = scorm_get_last_attempt($scorm->id, $userid); if ($scorm->maxattempt != 0 && $lastattempt >= $scorm->maxattempt) { $lastattempt = $scorm->maxattempt; } switch ($scorm->whatgrade) { case FIRSTATTEMPT: return scorm_grade_user_attempt($scorm, $userid, 1); break; case LASTATTEMPT: return scorm_grade_user_attempt($scorm, $userid, scorm_get_last_completed_attempt($scorm->id, $userid)); break; case HIGHESTATTEMPT: $maxscore = 0; for ($attempt = 1; $attempt <= $lastattempt; $attempt++) { $attemptscore = scorm_grade_user_attempt($scorm, $userid, $attempt); $maxscore = $attemptscore > $maxscore ? $attemptscore: $maxscore; } return $maxscore; break; case AVERAGEATTEMPT: $attemptcount = scorm_get_attempt_count($userid, $scorm, true); if (empty($attemptcount)) { return 0; } else { $attemptcount = count($attemptcount); } $lastattempt = scorm_get_last_attempt($scorm->id, $userid); $sumscore = 0; for ($attempt = 1; $attempt <= $lastattempt; $attempt++) { $attemptscore = scorm_grade_user_attempt($scorm, $userid, $attempt); $sumscore += $attemptscore; } return round($sumscore / $attemptcount); break; } }
function scorm_get_toc($user, $scorm, $liststyle, $currentorg = '', $scoid = '', $mode = 'normal', $attempt = '', $play = false) { global $CFG, $DB, $PAGE, $OUTPUT; $strexpand = get_string('expcoll', 'scorm'); $modestr = ''; if ($mode == 'browse') { $modestr = '&mode=' . $mode; } $result = new stdClass(); $result->toc = "<ul id='s0' class='{$liststyle}'>\n"; $tocmenus = array(); $result->prerequisites = true; $incomplete = false; // // Get the current organization infos // if (!empty($currentorg)) { if (($organizationtitle = $DB->get_field('scorm_scoes', 'title', array('scorm' => $scorm->id, 'identifier' => $currentorg))) != '') { $result->toc .= "\t<li>{$organizationtitle}</li>\n"; $tocmenus[] = $organizationtitle; } } // // If not specified retrieve the last attempt number // if (empty($attempt)) { $attempt = scorm_get_last_attempt($scorm->id, $user->id); } $result->attemptleft = $scorm->maxattempt - $attempt; if ($scoes = scorm_get_scoes($scorm->id, $currentorg)) { // // Retrieve user tracking data for each learning object // $usertracks = array(); foreach ($scoes as $sco) { if (!empty($sco->launch)) { if ($usertrack = scorm_get_tracks($sco->id, $user->id, $attempt)) { if ($usertrack->status == '') { $usertrack->status = 'notattempted'; } $usertracks[$sco->identifier] = $usertrack; } } } $level = 0; $sublist = 1; $previd = 0; $nextid = 0; $findnext = false; $parents[$level] = '/'; foreach ($scoes as $pos => $sco) { $isvisible = false; $sco->title = $sco->title; if (!isset($sco->isvisible) || isset($sco->isvisible) && $sco->isvisible == 'true') { $isvisible = true; } if ($parents[$level] != $sco->parent) { if ($newlevel = array_search($sco->parent, $parents)) { for ($i = 0; $i < $level - $newlevel; $i++) { $result->toc .= "\t\t</ul></li>\n"; } $level = $newlevel; } else { $i = $level; $closelist = ''; while ($i > 0 && $parents[$level] != $sco->parent) { $closelist .= "\t\t</ul></li>\n"; $i--; } if ($i == 0 && $sco->parent != $currentorg) { $style = ''; if (isset($_COOKIE['hide:SCORMitem' . $sco->id])) { $style = ' style="display: none;"'; } $result->toc .= "\t\t<li><ul id='s{$sublist}' class='{$liststyle}'{$style}>\n"; $level++; } else { $result->toc .= $closelist; $level = $i; } $parents[$level] = $sco->parent; } } if (isset($scoes[$pos + 1])) { $nextsco = $scoes[$pos + 1]; } else { $nextsco = false; } $nextisvisible = false; if (!isset($nextsco->isvisible) || isset($nextsco->isvisible) && $nextsco->isvisible == 'true') { $nextisvisible = true; } if ($nextisvisible && $nextsco !== false && $sco->parent != $nextsco->parent && ($level == 0 || $level > 0 && $nextsco->parent == $sco->identifier)) { $sublist++; $icon = 'minus'; if (isset($_COOKIE['hide:SCORMitem' . $nextsco->id])) { $icon = 'plus'; } $result->toc .= "\t\t" . '<li><a href="javascript:expandCollide(\'img' . $sublist . '\',\'s' . $sublist . '\',' . $nextsco->id . ');">' . '<img id="img' . $sublist . '" src="' . $OUTPUT->mod_icon_url('pix/' . $icon, 'scorm') . '" alt="' . $strexpand . '" title="' . $strexpand . '"/></a>'; } else { if ($isvisible) { $result->toc .= "\t\t" . '<li><img src="' . $OUTPUT->mod_icon_url('pix/spacer', 'scorm') . '" alt="" />'; } } if (empty($sco->title)) { $sco->title = $sco->identifier; } if (!empty($sco->launch)) { if ($isvisible) { $startbold = ''; $endbold = ''; $score = ''; if (empty($scoid) && $mode != 'normal') { $scoid = $sco->id; } if (isset($usertracks[$sco->identifier])) { $usertrack = $usertracks[$sco->identifier]; $strstatus = get_string($usertrack->status, 'scorm'); if ($sco->scormtype == 'sco') { $statusicon = '<img src="' . $OUTPUT->mod_icon_url('pix/' . $usertrack->status, 'scorm') . '" alt="' . $strstatus . '" title="' . $strstatus . '" />'; } else { $statusicon = '<img src="' . $OUTPUT->mod_icon_url('pix/assetc', 'scorm') . '" alt="' . get_string('assetlaunched', 'scorm') . '" title="' . get_string('assetlaunched', 'scorm') . '" />'; } if ($usertrack->status == 'notattempted' || $usertrack->status == 'incomplete' || $usertrack->status == 'browsed') { $incomplete = true; if ($play && empty($scoid)) { $scoid = $sco->id; } } if ($usertrack->score_raw != '') { $score = '(' . get_string('score', 'scorm') . ': ' . $usertrack->score_raw . ')'; } $strsuspended = get_string('suspended', 'scorm'); if (isset($usertrack->{'cmi.core.exit'}) && $usertrack->{'cmi.core.exit'} == 'suspend') { if ($usertrack->status != 'completed') { $statusicon = '<img src="' . $OUTPUT->mod_icon_url('pix/suspend', 'scorm') . '" alt="' . $strstatus . ' - ' . $strsuspended . '" title="' . $strstatus . ' - ' . $strsuspended . '" />'; } } } else { if ($play && empty($scoid)) { $scoid = $sco->id; } if ($sco->scormtype == 'sco') { $statusicon = '<img src="' . $OUTPUT->mod_icon_url('pix/notattempted', 'scorm') . '" alt="' . get_string('notattempted', 'scorm') . '" title="' . get_string('notattempted', 'scorm') . '" />'; $incomplete = true; } else { $statusicon = '<img src="' . $OUTPUT->mod_icon_url('pix/asset', 'scorm') . '" alt="' . get_string('asset', 'scorm') . '" title="' . get_string('asset', 'scorm') . '" />'; } } if ($sco->id == $scoid) { $startbold = '<b>'; $endbold = '</b>'; $findnext = true; $shownext = isset($sco->next) ? $sco->next : 0; $showprev = isset($sco->prev) ? $sco->prev : 0; } if ($nextid == 0 && scorm_count_launchable($scorm->id, $currentorg) > 1 && $nextsco !== false && !$findnext) { if (!empty($sco->launch)) { $previd = $sco->id; } } require_once 'sequencinglib.php'; if (scorm_seq_evaluate($sco->id, $usertracks)) { if ($sco->id == $scoid) { $result->prerequisites = true; } $url = $CFG->wwwroot . '/mod/scorm/player.php?a=' . $scorm->id . '&currentorg=' . $currentorg . $modestr . '&scoid=' . $sco->id; $result->toc .= $statusicon . ' ' . $startbold . '<a href="' . $url . '">' . format_string($sco->title) . '</a>' . $score . $endbold . "</li>\n"; $tocmenus[$sco->id] = scorm_repeater('−', $level) . '>' . format_string($sco->title); } else { if ($sco->id == $scoid) { $result->prerequisites = false; } $result->toc .= ' ' . format_string($sco->title) . "</li>\n"; } } } else { $result->toc .= ' ' . format_string($sco->title) . "</li>\n"; } if ($nextsco !== false && $nextid == 0 && $findnext) { if (!empty($nextsco->launch)) { $nextid = $nextsco->id; } } } for ($i = 0; $i < $level; $i++) { $result->toc .= "\t\t</ul></li>\n"; } if ($play) { $sco = $DB->get_record('scorm_scoes', array('id' => $scoid)); $sco->previd = $previd; $sco->nextid = $nextid; $result->sco = $sco; $result->incomplete = $incomplete; } else { $result->incomplete = $incomplete; } } $result->toc .= "\t</ul>\n"; if ($scorm->hidetoc == 0) { $PAGE->requires->data_for_js('scormdata', array('plusicon' => $OUTPUT->mod_icon_url('pix/plus', 'scorm'), 'minusicon' => $OUTPUT->mod_icon_url('pix/minus', 'scorm'))); $PAGE->requires->js('mod/scorm/datamodels/scorm_datamodels.js'); } $url = $CFG->wwwroot . '/mod/scorm/player.php?a=' . $scorm->id . '¤torg=' . $currentorg . $modestr; $select = html_select::make_popup_form($url, 'scoid', $tocmenus, "tocmenu", $sco->id); $select->nothinglabel = false; $result->tocmenu = $OUTPUT->select($select); return $result; }
function scorm_get_toc($user, $scorm, $liststyle, $currentorg = '', $scoid = '', $mode = 'normal', $attempt = '', $play = false) { global $CFG; $strexpand = get_string('expcoll', 'scorm'); $modestr = ''; if ($mode == 'browse') { $modestr = '&mode=' . $mode; } $scormpixdir = $CFG->modpixpath . '/scorm/pix'; $result = new stdClass(); $result->toc = "<ul id='s0' class='{$liststyle}'>\n"; $tocmenus = array(); $result->prerequisites = true; $incomplete = false; // // Get the current organization infos // $organizationsql = ''; if (!empty($currentorg)) { if (($organizationtitle = get_field('scorm_scoes', 'title', 'scorm', $scorm->id, 'identifier', $currentorg)) != '') { $result->toc .= "\t<li>{$organizationtitle}</li>\n"; $tocmenus[] = $organizationtitle; } $organizationsql = "AND organization='{$currentorg}'"; } // // If not specified retrieve the last attempt number // if (empty($attempt)) { $attempt = scorm_get_last_attempt($scorm->id, $user->id); } $result->attemptleft = $scorm->maxattempt - $attempt; if ($scoes = get_records_select('scorm_scoes', "scorm='{$scorm->id}' {$organizationsql} order by id ASC")) { // // Retrieve user tracking data for each learning object // $usertracks = array(); foreach ($scoes as $sco) { if (!empty($sco->launch)) { if ($usertrack = scorm_get_tracks($sco->id, $user->id, $attempt)) { if ($usertrack->status == '') { $usertrack->status = 'notattempted'; } $usertracks[$sco->identifier] = $usertrack; } } } $level = 0; $sublist = 1; $previd = 0; $nextid = 0; $findnext = false; $parents[$level] = '/'; foreach ($scoes as $sco) { $isvisible = false; $sco->title = stripslashes($sco->title); if ($optionaldatas = scorm_get_sco($sco->id, SCO_DATA)) { if (!isset($optionaldatas->isvisible) || isset($optionaldatas->isvisible) && $optionaldatas->isvisible == 'true') { $isvisible = true; } } else { $isvisible = true; } if ($parents[$level] != $sco->parent) { if ($newlevel = array_search($sco->parent, $parents)) { for ($i = 0; $i < $level - $newlevel; $i++) { $result->toc .= "\t\t</ul></li>\n"; } $level = $newlevel; } else { $i = $level; $closelist = ''; while ($i > 0 && $parents[$level] != $sco->parent) { $closelist .= "\t\t</ul></li>\n"; $i--; } if ($i == 0 && $sco->parent != $currentorg) { $style = ''; if (isset($_COOKIE['hide:SCORMitem' . $sco->id])) { $style = ' style="display: none;"'; } $result->toc .= "\t\t<li><ul id='s{$sublist}' class='{$liststyle}'{$style}>\n"; $level++; } else { $result->toc .= $closelist; $level = $i; } $parents[$level] = $sco->parent; } } if ($isvisible) { $result->toc .= "\t\t<li>"; } $nextsco = next($scoes); $nextisvisible = false; if ($nextsco !== false && ($optionaldatas = scorm_get_sco($nextsco->id, SCO_DATA))) { if (!isset($optionaldatas->isvisible) || isset($optionaldatas->isvisible) && $optionaldatas->isvisible == 'true') { $nextisvisible = true; } } if ($nextisvisible && $nextsco !== false && $sco->parent != $nextsco->parent && ($level == 0 || $level > 0 && $nextsco->parent == $sco->identifier)) { $sublist++; $icon = 'minus'; if (isset($_COOKIE['hide:SCORMitem' . $nextsco->id])) { $icon = 'plus'; } $result->toc .= '<a href="javascript:expandCollide(\'img' . $sublist . '\',' . $sublist . ',' . $nextsco->id . ');"><img id="img' . $sublist . '" src="' . $scormpixdir . '/' . $icon . '.gif" alt="' . $strexpand . '" title="' . $strexpand . '"/></a>'; // $result->toc .= '<a href="#" onclick="elementToggleHide(\''.$sublist.'\',true);"><img id="img'.$sublist.'" src="'.$scormpixdir.'/'.$icon.'.gif" alt="'.$strexpand.'" title="'.$strexpand.'"/></a>'; } else { if ($isvisible) { $result->toc .= '<img src="' . $scormpixdir . '/spacer.gif" />'; } } if (empty($sco->title)) { $sco->title = $sco->identifier; } if (!empty($sco->launch)) { if ($isvisible) { $startbold = ''; $endbold = ''; $score = ''; if (empty($scoid) && $mode != 'normal') { $scoid = $sco->id; } if (isset($usertracks[$sco->identifier])) { $usertrack = $usertracks[$sco->identifier]; $strstatus = get_string($usertrack->status, 'scorm'); if ($sco->scormtype == 'sco') { $statusicon = '<img src="' . $scormpixdir . '/' . $usertrack->status . '.gif" alt="' . $strstatus . '" title="' . $strstatus . '" />'; } else { $statusicon = '<img src="' . $scormpixdir . '/assetc.gif" alt="' . get_string('assetlaunched', 'scorm') . '" title="' . get_string('assetlaunched', 'scorm') . '" />'; } if ($usertrack->status == 'notattempted' || $usertrack->status == 'incomplete' || $usertrack->status == 'browsed') { $incomplete = true; if ($play && empty($scoid)) { $scoid = $sco->id; } } if ($usertrack->score_raw != '') { $score = '(' . get_string('score', 'scorm') . ': ' . $usertrack->score_raw . ')'; } $strsuspended = get_string('suspended', 'scorm'); if (isset($usertrack->{'cmi.core.exit'}) && $usertrack->{'cmi.core.exit'} == 'suspend') { $statusicon = '<img src="' . $scormpixdir . '/suspend.gif" alt="' . $strstatus . ' - ' . $strsuspended . '" title="' . $strstatus . ' - ' . $strsuspended . '" />'; } } else { if ($play && empty($scoid)) { $scoid = $sco->id; } $incomplete = true; if ($sco->scormtype == 'sco') { $statusicon = '<img src="' . $scormpixdir . '/notattempted.gif" alt="' . get_string('notattempted', 'scorm') . '" title="' . get_string('notattempted', 'scorm') . '" />'; } else { $statusicon = '<img src="' . $scormpixdir . '/asset.gif" alt="' . get_string('asset', 'scorm') . '" title="' . get_string('asset', 'scorm') . '" />'; } } if ($sco->id == $scoid) { $scodata = scorm_get_sco($sco->id, SCO_DATA); $startbold = '<b>'; $endbold = '</b>'; $findnext = true; $shownext = isset($scodata->next) ? $scodata->next : 0; $showprev = isset($scodata->previous) ? $scodata->previous : 0; } if ($nextid == 0 && scorm_count_launchable($scorm->id, $currentorg) > 1 && $nextsco !== false && !$findnext) { if (!empty($sco->launch)) { $previd = $sco->id; } } if (empty($sco->prerequisites) || scorm_eval_prerequisites($sco->prerequisites, $usertracks)) { if ($sco->id == $scoid) { $result->prerequisites = true; } $url = $CFG->wwwroot . '/mod/scorm/player.php?a=' . $scorm->id . '&currentorg=' . $currentorg . $modestr . '&scoid=' . $sco->id; $result->toc .= $statusicon . ' ' . $startbold . '<a href="' . $url . '">' . format_string($sco->title) . '</a>' . $score . $endbold . "</li>\n"; $tocmenus[$sco->id] = scorm_repeater('−', $level) . '>' . format_string($sco->title); } else { if ($sco->id == $scoid) { $result->prerequisites = false; } $result->toc .= $statusicon . ' ' . format_string($sco->title) . "</li>\n"; } } } else { $result->toc .= ' ' . format_string($sco->title) . "</li>\n"; } if ($nextsco !== false && $nextid == 0 && $findnext) { if (!empty($nextsco->launch)) { $nextid = $nextsco->id; } } } for ($i = 0; $i < $level; $i++) { $result->toc .= "\t\t</ul></li>\n"; } if ($play) { // it is possible that scoid is still not set, in this case we dont want an empty object if ($scoid) { $sco = scorm_get_sco($scoid); } $sco->previd = $previd; $sco->nextid = $nextid; $result->sco = $sco; $result->incomplete = $incomplete; } else { $result->incomplete = $incomplete; } } $result->toc .= "\t</ul>\n"; if ($scorm->hidetoc == 0) { $result->toc .= ' <script type="text/javascript"> //<![CDATA[ function expandCollide(which,list,item) { var nn=document.ids?true:false var w3c=document.getElementById?true:false var beg=nn?"document.ids.":w3c?"document.getElementById(":"document.all."; var mid=w3c?").style":".style"; which = which.substring(0,(which.length)); if (eval(beg+list+mid+".display") != "none") { document.getElementById(which).src = "' . $scormpixdir . '/plus.gif"; eval(beg+list+mid+".display=\'none\';"); new cookie("hide:SCORMitem" + item, 1, 356, "/").set(); } else { document.getElementById(which).src = "' . $scormpixdir . '/minus.gif"; eval(beg+list+mid+".display=\'block\';"); new cookie("hide:SCORMitem" + item, 1, -1, "/").set(); } } //]]> </script>' . "\n"; } $url = $CFG->wwwroot . '/mod/scorm/player.php?a=' . $scorm->id . '&currentorg=' . $currentorg . $modestr . '&scoid='; $result->tocmenu = popup_form($url, $tocmenus, "tocmenu", $sco->id, '', '', '', true); return $result; }
function scorm_grade_user($scorm, $userid, $time = false) { // this treatment is necessary as the whatgrade field was not in the DB // and so whatgrade and grademethod are combined in grademethod 10s are whatgrade // and 1s are grademethod $whatgrade = intval($scorm->grademethod / 10); // insure we dont grade user beyond $scorm->maxattempt settings $lastattempt = scorm_get_last_attempt($scorm->id, $userid); if ($scorm->maxattempt != 0 && $lastattempt >= $scorm->maxattempt) { $lastattempt = $scorm->maxattempt; } switch ($whatgrade) { case FIRSTATTEMPT: return scorm_grade_user_attempt($scorm, $userid, 1, $time); break; case LASTATTEMPT: return scorm_grade_user_attempt($scorm, $userid, scorm_get_last_attempt($scorm->id, $userid), $time); break; case HIGHESTATTEMPT: $maxscore = 0; $attempttime = 0; for ($attempt = 1; $attempt <= $lastattempt; $attempt++) { $attemptscore = scorm_grade_user_attempt($scorm, $userid, $attempt, $time); if ($time) { if ($attemptscore->score > $maxscore) { $maxscore = $attemptscore->score; $attempttime = $attemptscore->time; } } else { $maxscore = $attemptscore > $maxscore ? $attemptscore : $maxscore; } } if ($time) { $result = new stdClass(); $result->score = $maxscore; $result->time = $attempttime; return $result; } else { return $maxscore; } break; case AVERAGEATTEMPT: $lastattempt = scorm_get_last_attempt($scorm->id, $userid); $sumscore = 0; for ($attempt = 1; $attempt <= $lastattempt; $attempt++) { $attemptscore = scorm_grade_user_attempt($scorm, $userid, $attempt, $time); if ($time) { $sumscore += $attemptscore->score; } else { $sumscore += $attemptscore; } } if ($lastattempt > 0) { $score = $sumscore / $lastattempt; } else { $score = 0; } if ($time) { $result = new stdClass(); $result->score = $score; $result->time = $attemptscore->time; return $result; } else { return $score; } break; } }
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; }
function scorm_grade_user($scorm, $userid, $time = false) { $whatgrade = intval($scorm->grademethod / 10); switch ($whatgrade) { case FIRSTATTEMPT: return scorm_grade_user_attempt($scorm, $userid, 1, $time); break; case LASTATTEMPT: return scorm_grade_user_attempt($scorm, $userid, scorm_get_last_attempt($scorm->id, $userid), $time); break; case HIGHESTATTEMPT: $lastattempt = scorm_get_last_attempt($scorm->id, $userid); $maxscore = 0; $attempttime = 0; for ($attempt = 1; $attempt <= $lastattempt; $attempt++) { $attemptscore = scorm_grade_user_attempt($scorm, $userid, $attempt, $time); if ($time) { if ($attemptscore->score > $maxscore) { $maxscore = $attemptscore->score; $attempttime = $attemptscore->time; } } else { $maxscore = $attemptscore > $maxscore ? $attemptscore : $maxscore; } } if ($time) { $result = new stdClass(); $result->score = $maxscore; $result->time = $attempttime; return $result; } else { return $maxscore; } break; case AVERAGEATTEMPT: $lastattempt = scorm_get_last_attempt($scorm->id, $userid); $sumscore = 0; for ($attempt = 1; $attempt <= $lastattempt; $attempt++) { $attemptscore = scorm_grade_user_attempt($scorm, $userid, $attempt, $time); if ($time) { $sumscore += $attemptscore->score; } else { $sumscore += $attemptscore; } } if ($lastattempt > 0) { $score = $sumscore / $lastattempt; } else { $score = 0; } if ($time) { $result = new stdClass(); $result->score = $score; $result->time = $attemptscore->time; return $result; } else { return $score; } break; } }
/** * Retrieves SCO tracking data for the given user id and attempt number * * @param int $scoid the sco id * @param int $userid the user id * @param int $attempt the attempt number * @return array warnings and the scoes data * @since Moodle 3.0 */ public static function get_scorm_sco_tracks($scoid, $userid, $attempt = 0) { global $USER, $DB; $params = self::validate_parameters(self::get_scorm_sco_tracks_parameters(), array('scoid' => $scoid, 'userid' => $userid, 'attempt' => $attempt)); $tracks = 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); $user = core_user::get_user($params['userid'], '*', MUST_EXIST); core_user::require_active_user($user); // Extra checks so only users with permissions can view other users attempts. if ($USER->id != $user->id) { require_capability('mod/scorm:viewreport', $context); } scorm_require_available($scorm, true, $context); if (empty($params['attempt'])) { $params['attempt'] = scorm_get_last_attempt($scorm->id, $user->id); } $attempted = false; if ($scormtracks = scorm_get_tracks($sco->id, $params['userid'], $params['attempt'])) { // Check if attempted. if ($scormtracks->status != '') { $attempted = true; foreach ($scormtracks as $element => $value) { $tracks[] = array('element' => $element, 'value' => $value); } } } if (!$attempted) { $warnings[] = array('item' => 'attempt', 'itemid' => $params['attempt'], 'warningcode' => 'notattempted', 'message' => get_string('notattempted', 'scorm')); } $result = array(); $result['data']['attempt'] = $params['attempt']; $result['data']['tracks'] = $tracks; $result['warnings'] = $warnings; return $result; }
function scorm_get_toc($user, $scorm, $liststyle, $currentorg = '', $scoid = '', $mode = 'normal', $attempt = '', $play = false, $tocheader = false) { global $CFG, $DB, $PAGE, $OUTPUT; $strexpand = get_string('expcoll', 'scorm'); $modestr = ''; if ($mode == 'browse') { $modestr = '&mode=' . $mode; } $result = new stdClass(); //$result->toc = "<ul id='s0' class='$liststyle'>\n"; if ($tocheader) { $result->toc = '<div id="scorm_layout">'; $result->toc .= '<div id="scorm_toc">'; $result->toc .= '<div id="scorm_tree">'; } $result->toc .= '<ul>'; $tocmenus = array(); $result->prerequisites = true; $incomplete = false; // // Get the current organization infos // if (!empty($currentorg)) { if (($organizationtitle = $DB->get_field('scorm_scoes', 'title', array('scorm' => $scorm->id, 'identifier' => $currentorg))) != '') { if ($play) { $result->toctitle = "{$organizationtitle}"; } else { $result->toc .= "\t<li>{$organizationtitle}</li>\n"; } $tocmenus[] = $organizationtitle; } } // // If not specified retrieve the last attempt number // if (empty($attempt)) { $attempt = scorm_get_last_attempt($scorm->id, $user->id); } $result->attemptleft = $scorm->maxattempt - $attempt; if ($scoes = scorm_get_scoes($scorm->id, $currentorg)) { // // Retrieve user tracking data for each learning object // $usertracks = array(); foreach ($scoes as $sco) { if (!empty($sco->launch)) { if (empty($scoid)) { $scoid = $sco->id; } if ($usertrack = scorm_get_tracks($sco->id, $user->id, $attempt)) { if ($usertrack->status == '') { $usertrack->status = 'notattempted'; } $usertracks[$sco->identifier] = $usertrack; } } } $level = 0; $sublist = 1; $previd = 0; $nextid = 0; $findnext = false; $parents[$level] = '/'; foreach ($scoes as $pos => $sco) { $isvisible = false; $sco->title = $sco->title; if (!isset($sco->isvisible) || isset($sco->isvisible) && $sco->isvisible == 'true') { $isvisible = true; } if ($parents[$level] != $sco->parent) { if ($newlevel = array_search($sco->parent, $parents)) { for ($i = 0; $i < $level - $newlevel; $i++) { $result->toc .= "\t\t</li></ul></li>\n"; } $level = $newlevel; } else { $i = $level; $closelist = ''; while ($i > 0 && $parents[$level] != $sco->parent) { $closelist .= "\t\t</li></ul></li>\n"; $i--; } if ($i == 0 && $sco->parent != $currentorg) { $style = ''; if (isset($_COOKIE['hide:SCORMitem' . $sco->id])) { $style = ' style="display: none;"'; } //$result->toc .= "\t\t<li><ul id='s$sublist' class='$liststyle'$style>\n"; $result->toc .= "\t\t<ul>\n"; $level++; } else { $result->toc .= $closelist; $level = $i; } $parents[$level] = $sco->parent; } } if ($isvisible) { $result->toc .= "\t\t<li>"; } if (isset($scoes[$pos + 1])) { $nextsco = $scoes[$pos + 1]; } else { $nextsco = false; } $nextisvisible = false; if (!isset($nextsco->isvisible) || isset($nextsco->isvisible) && $nextsco->isvisible == 'true') { $nextisvisible = true; } if ($nextisvisible && $nextsco !== false && $sco->parent != $nextsco->parent && ($level == 0 || $level > 0 && $nextsco->parent == $sco->identifier)) { $sublist++; $icon = 'minus'; if (isset($_COOKIE['hide:SCORMitem' . $nextsco->id])) { $icon = 'plus'; } //$result->toc .= '<a href="javascript:expandCollide(\'img'.$sublist.'\',\'s'.$sublist.'\','.$nextsco->id.');"><img id="img'.$sublist.'" src="'.$OUTPUT->pix_url($icon, 'scorm').'" alt="'.$strexpand.'" title="'.$strexpand.'"/></a>'; } else { if ($isvisible) { //$result->toc .= '<img src="'.$OUTPUT->pix_url('spacer', 'scorm').'" alt="" />'; } } if (empty($sco->title)) { $sco->title = $sco->identifier; } if (!empty($sco->launch)) { if ($isvisible) { $startbold = ''; $endbold = ''; $score = ''; if (empty($scoid) && $mode != 'normal') { $scoid = $sco->id; } if (isset($usertracks[$sco->identifier])) { $usertrack = $usertracks[$sco->identifier]; $strstatus = get_string($usertrack->status, 'scorm'); if ($sco->scormtype == 'sco') { $statusicon = '<img src="' . $OUTPUT->pix_url($usertrack->status, 'scorm') . '" alt="' . $strstatus . '" title="' . $strstatus . '" />'; } else { $statusicon = '<img src="' . $OUTPUT->pix_url('assetc', 'scorm') . '" alt="' . get_string('assetlaunched', 'scorm') . '" title="' . get_string('assetlaunched', 'scorm') . '" />'; } if ($usertrack->status == 'notattempted' || $usertrack->status == 'incomplete' || $usertrack->status == 'browsed') { $incomplete = true; if ($play && empty($scoid)) { $scoid = $sco->id; } } if ($usertrack->score_raw != '') { $score = '(' . get_string('score', 'scorm') . ': ' . $usertrack->score_raw . ')'; } $strsuspended = get_string('suspended', 'scorm'); if ($incomplete && isset($usertrack->{'cmi.core.exit'}) && $usertrack->{'cmi.core.exit'} == 'suspend') { $statusicon = '<img src="' . $OUTPUT->pix_url('suspend', 'scorm') . '" alt="' . $strstatus . ' - ' . $strsuspended . '" title="' . $strstatus . ' - ' . $strsuspended . '" />'; } } else { if ($play && empty($scoid)) { $scoid = $sco->id; } $incomplete = true; if ($sco->scormtype == 'sco') { $statusicon = '<img src="' . $OUTPUT->pix_url('notattempted', 'scorm') . '" alt="' . get_string('notattempted', 'scorm') . '" title="' . get_string('notattempted', 'scorm') . '" />'; } else { $statusicon = '<img src="' . $OUTPUT->pix_url('asset', 'scorm') . '" alt="' . get_string('asset', 'scorm') . '" title="' . get_string('asset', 'scorm') . '" />'; } } if ($sco->id == $scoid) { $startbold = '<b>'; $endbold = '</b>'; $findnext = true; $shownext = isset($sco->next) ? $sco->next : 0; $showprev = isset($sco->previous) ? $sco->previous : 0; } if ($nextid == 0 && scorm_count_launchable($scorm->id, $currentorg) > 1 && $nextsco !== false && !$findnext) { if (!empty($sco->launch)) { $previd = $sco->id; } } if (empty($sco->prerequisites) || scorm_eval_prerequisites($sco->prerequisites, $usertracks)) { if ($sco->id == $scoid) { $result->prerequisites = true; } $url = $CFG->wwwroot . '/mod/scorm/player.php?a=' . $scorm->id . '&currentorg=' . $currentorg . $modestr . '&scoid=' . $sco->id; $thisscoidstr = '&scoid=' . $sco->id; //$link = $CFG->wwwroot.'/mod/scorm/loadSCO.php?a='.$scorm->id.$thisscoidstr.$modestr; $link = 'a=' . $scorm->id . $thisscoidstr . '¤torg=' . $currentorg . $modestr . '&attempt=' . $attempt; //$result->toc .= $statusicon.' '.$startbold.'<a href="'.$url.'">'.format_string($sco->title).'</a>'.$score.$endbold."</li>\n"; //$result->toc .= '<a title="'.$link.'">'.$statusicon.' '.format_string($sco->title).' '.$score.'</a>'; if ($sco->launch) { $result->toc .= '<a title="' . $link . '">' . $statusicon . ' ' . format_string($sco->title) . ' ' . $score . '</a>'; } else { $result->toc .= '<span>' . $statusicon . ' ' . format_string($sco->title) . '</span>'; } $tocmenus[$sco->id] = scorm_repeater('−', $level) . '>' . format_string($sco->title); } else { if ($sco->id == $scoid) { $result->prerequisites = false; } if ($play) { // should be disabled $result->toc .= '<span>' . $statusicon . ' ' . format_string($sco->title) . '</span>'; } else { $result->toc .= $statusicon . ' ' . format_string($sco->title) . "\n"; } } if ($nextsco === false || $nextsco->parent == $sco->parent) { $result->toc .= '</li>'; } } } else { $result->toc .= ' ' . format_string($sco->title) . "</li>\n"; } if ($nextsco !== false && $nextid == 0 && $findnext) { if (!empty($nextsco->launch)) { $nextid = $nextsco->id; } } } for ($i = 0; $i < $level; $i++) { $result->toc .= "\t\t</ul></li>\n"; } if ($play) { $sco = scorm_get_sco($scoid); $sco->previd = $previd; $sco->nextid = $nextid; $result->sco = $sco; $result->incomplete = $incomplete; } else { $result->incomplete = $incomplete; } } $result->toc .= '</ul>'; // NEW IMS TOC if ($tocheader) { $result->toc .= '</div></div></div>'; $result->toc .= '<div id="scorm_navpanel"></div>'; } if ($scorm->hidetoc == 0) { $result->toc .= html_writer::script(js_writer::set_variable('scormdata', array('plusicon' => $OUTPUT->pix_url('plus', 'scorm'), 'minusicon' => $OUTPUT->pix_url('minus', 'scorm')))); $result->toc .= html_writer::script('', $CFG->wwwroot . '/lib/cookies.js'); $result->toc .= html_writer::script('', $CFG->wwwroot . '/mod/scorm/datamodels/scorm_datamodels.js'); } $url = new moodle_url('/mod/scorm/player.php?a=' . $scorm->id . '¤torg=' . $currentorg . $modestr); $result->tocmenu = $OUTPUT->single_select($url, 'scoid', $tocmenus, $sco->id, null, "tocmenu"); return $result; }
function scorm_get_toc($user, $scorm, $cmid, $toclink=TOCJSLINK, $currentorg='', $scoid='', $mode='normal', $attempt='', $play=false, $tocheader=false) { global $CFG, $DB, $OUTPUT; if (empty($attempt)) { $attempt = scorm_get_last_attempt($scorm->id, $user->id); } $result = new stdClass(); $organizationsco = null; if ($tocheader) { $result->toc = html_writer::start_div('yui3-g-r', array('id' => 'scorm_layout')); $result->toc .= html_writer::start_div('yui3-u-1-5', array('id' => 'scorm_toc')); $result->toc .= html_writer::div('', '', array('id' => 'scorm_toc_title')); $result->toc .= html_writer::start_div('', array('id' => 'scorm_tree')); } if (!empty($currentorg)) { $organizationsco = $DB->get_record('scorm_scoes', array('scorm' => $scorm->id, 'identifier' => $currentorg)); if (!empty($organizationsco->title)) { if ($play) { $result->toctitle = $organizationsco->title; } } } $scoes = scorm_get_toc_object($user, $scorm, $currentorg, $scoid, $mode, $attempt, $play, $organizationsco); $treeview = scorm_format_toc_for_treeview($user, $scorm, $scoes['scoes'][0]->children, $scoes['usertracks'], $cmid, $toclink, $currentorg, $attempt, $play, $organizationsco, false); if ($tocheader) { $result->toc .= $treeview->toc; } else { $result->toc = $treeview->toc; } if (!empty($scoes['scoid'])) { $scoid = $scoes['scoid']; } if (empty($scoid)) { // If this is a normal package with an org sco and child scos get the first child. if (!empty($scoes['scoes'][0]->children)) { $result->sco = $scoes['scoes'][0]->children[0]; } else { // This package only has one sco - it may be a simple external AICC package. $result->sco = $scoes['scoes'][0]; } } else { $result->sco = scorm_get_sco($scoid); } if ($scorm->hidetoc == SCORM_TOC_POPUP) { $tocmenu = scorm_format_toc_for_droplist($scorm, $scoes['scoes'][0]->children, $scoes['usertracks'], $currentorg, $organizationsco); $modestr = ''; if ($mode != 'normal') { $modestr = '&mode='.$mode; } $url = new moodle_url('/mod/scorm/player.php?a='.$scorm->id.'¤torg='.$currentorg.$modestr); $result->tocmenu = $OUTPUT->single_select($url, 'scoid', $tocmenu, $result->sco->id, null, "tocmenu"); } $result->prerequisites = $treeview->prerequisites; $result->incomplete = $treeview->incomplete; $result->attemptleft = $treeview->attemptleft; if ($tocheader) { $result->toc .= html_writer::end_div().html_writer::end_div(); $result->toc .= html_writer::start_div('', array('id' => 'scorm_toc_toggle')); $result->toc .= html_writer::tag('button', '', array('id' => 'scorm_toc_toggle_btn')).html_writer::end_div(); $result->toc .= html_writer::start_div('', array('id' => 'scorm_content')); $result->toc .= html_writer::div('', '', array('id' => 'scorm_navpanel')); $result->toc .= html_writer::end_div().html_writer::end_div(); } return $result; }
$table->size[] = '*'; $table->head[] = get_string('started', 'scorm'); $table->align[] = 'center'; $table->wrap[] = 'nowrap'; $table->size[] = '*'; $table->head[] = get_string('last', 'scorm'); $table->align[] = 'center'; $table->wrap[] = 'nowrap'; $table->size[] = '*'; $table->head[] = get_string('score', 'scorm'); $table->align[] = 'center'; $table->wrap[] = 'nowrap'; $table->size[] = '*'; foreach ($scousers as $scouser) { $userdata = scorm_get_user_data($scouser->userid); $attempt = scorm_get_last_attempt($scorm->id, $scouser->userid); for ($a = 1; $a <= $attempt; $a++) { $row = array(); $row[] = print_user_picture($scouser->userid, $course->id, $userdata->picture, false, true); $row[] = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $scouser->userid . '&course=' . $course->id . '">' . fullname($userdata) . '</a>'; $row[] = '<a href="report.php?a=' . $scorm->id . '&user='******'&attempt=' . $a . '">' . $a . '</a>'; $select = 'scormid = ' . $scorm->id . ' and userid = ' . $scouser->userid . ' and attempt = ' . $a; $timetracks = get_record_select('scorm_scoes_track', $select, 'min(timemodified) as started, max(timemodified) as last'); $row[] = userdate($timetracks->started, get_string('strftimedaydatetime')); $row[] = userdate($timetracks->last, get_string('strftimedaydatetime')); $row[] = scorm_grade_user_attempt($scorm, $scouser->userid, $a); $table->data[] = $row; } } } print_table($table);
function scorm_get_toc($user, $scorm, $liststyle, $currentorg = '', $scoid = '', $mode = 'normal', $attempt = '', $play = false) { global $CFG, $DB; $strexpand = get_string('expcoll', 'scorm'); $modestr = ''; if ($mode == 'browse') { $modestr = '&mode=' . $mode; } $scormpixdir = $CFG->modpixpath . '/scorm/pix'; $result = new stdClass(); $result->toc = "<ul id='s0' class='{$liststyle}'>\n"; $tocmenus = array(); $result->prerequisites = true; $incomplete = false; // // Get the current organization infos // if (!empty($currentorg)) { if (($organizationtitle = $DB->get_field('scorm_scoes', 'title', array('scorm' => $scorm->id, 'identifier' => $currentorg))) != '') { $result->toc .= "\t<li>{$organizationtitle}</li>\n"; $tocmenus[] = $organizationtitle; } } // // If not specified retrieve the last attempt number // if (empty($attempt)) { $attempt = scorm_get_last_attempt($scorm->id, $user->id); } $result->attemptleft = $scorm->maxattempt - $attempt; if ($scoes = scorm_get_scoes($scorm->id, $currentorg)) { // // Retrieve user tracking data for each learning object // $usertracks = array(); foreach ($scoes as $sco) { if (!empty($sco->launch)) { if ($usertrack = scorm_get_tracks($sco->id, $user->id, $attempt)) { if ($usertrack->status == '') { $usertrack->status = 'notattempted'; } $usertracks[$sco->identifier] = $usertrack; } } } $level = 0; $sublist = 1; $previd = 0; $nextid = 0; $findnext = false; $parents[$level] = '/'; foreach ($scoes as $pos => $sco) { $isvisible = false; $sco->title = $sco->title; if (!isset($sco->isvisible) || isset($sco->isvisible) && $sco->isvisible == 'true') { $isvisible = true; } if ($parents[$level] != $sco->parent) { if ($newlevel = array_search($sco->parent, $parents)) { for ($i = 0; $i < $level - $newlevel; $i++) { $result->toc .= "\t\t</ul></li>\n"; } $level = $newlevel; } else { $i = $level; $closelist = ''; while ($i > 0 && $parents[$level] != $sco->parent) { $closelist .= "\t\t</ul></li>\n"; $i--; } if ($i == 0 && $sco->parent != $currentorg) { $style = ''; if (isset($_COOKIE['hide:SCORMitem' . $sco->id])) { $style = ' style="display: none;"'; } $result->toc .= "\t\t<li><ul id='s{$sublist}' class='{$liststyle}'{$style}>\n"; $level++; } else { $result->toc .= $closelist; $level = $i; } $parents[$level] = $sco->parent; } } if (isset($scoes[$pos + 1])) { $nextsco = $scoes[$pos + 1]; } else { $nextsco = false; } $nextisvisible = false; if (!isset($nextsco->isvisible) || isset($nextsco->isvisible) && $nextsco->isvisible == 'true') { $nextisvisible = true; } if ($nextisvisible && $nextsco !== false && $sco->parent != $nextsco->parent && ($level == 0 || $level > 0 && $nextsco->parent == $sco->identifier)) { $sublist++; $icon = 'minus'; if (isset($_COOKIE['hide:SCORMitem' . $nextsco->id])) { $icon = 'plus'; } $result->toc .= "\t\t" . '<li><a href="javascript:expandCollide(\'img' . $sublist . '\',\'s' . $sublist . '\',' . $nextsco->id . ');">' . '<img id="img' . $sublist . '" src="' . $scormpixdir . '/' . $icon . '.gif" alt="' . $strexpand . '" title="' . $strexpand . '"/></a>'; } else { if ($isvisible) { $result->toc .= "\t\t" . '<li><img src="' . $scormpixdir . '/spacer.gif" alt="" />'; } } if (empty($sco->title)) { $sco->title = $sco->identifier; } if (!empty($sco->launch)) { if ($isvisible) { $startbold = ''; $endbold = ''; $score = ''; if (empty($scoid) && $mode != 'normal') { $scoid = $sco->id; } if (isset($usertracks[$sco->identifier])) { $usertrack = $usertracks[$sco->identifier]; $strstatus = get_string($usertrack->status, 'scorm'); if ($sco->scormtype == 'sco') { $statusicon = '<img src="' . $scormpixdir . '/' . $usertrack->status . '.gif" alt="' . $strstatus . '" title="' . $strstatus . '" />'; } else { $statusicon = '<img src="' . $scormpixdir . '/assetc.gif" alt="' . get_string('assetlaunched', 'scorm') . '" title="' . get_string('assetlaunched', 'scorm') . '" />'; } if ($usertrack->status == 'notattempted' || $usertrack->status == 'incomplete' || $usertrack->status == 'browsed') { $incomplete = true; if ($play && empty($scoid)) { $scoid = $sco->id; } } if ($usertrack->score_raw != '') { $score = '(' . get_string('score', 'scorm') . ': ' . $usertrack->score_raw . ')'; } $strsuspended = get_string('suspended', 'scorm'); if (isset($usertrack->{'cmi.core.exit'}) && $usertrack->{'cmi.core.exit'} == 'suspend') { if ($usertrack->status != 'completed') { $statusicon = '<img src="' . $scormpixdir . '/suspend.gif" alt="' . $strstatus . ' - ' . $strsuspended . '" title="' . $strstatus . ' - ' . $strsuspended . '" />'; } } } else { if ($play && empty($scoid)) { $scoid = $sco->id; } if ($sco->scormtype == 'sco') { $statusicon = '<img src="' . $scormpixdir . '/notattempted.gif" alt="' . get_string('notattempted', 'scorm') . '" title="' . get_string('notattempted', 'scorm') . '" />'; $incomplete = true; } else { $statusicon = '<img src="' . $scormpixdir . '/asset.gif" alt="' . get_string('asset', 'scorm') . '" title="' . get_string('asset', 'scorm') . '" />'; } } if ($sco->id == $scoid) { $startbold = '<b>'; $endbold = '</b>'; $findnext = true; $shownext = isset($sco->next) ? $sco->next : 0; $showprev = isset($sco->prev) ? $sco->prev : 0; } if ($nextid == 0 && scorm_count_launchable($scorm->id, $currentorg) > 1 && $nextsco !== false && !$findnext) { if (!empty($sco->launch)) { $previd = $sco->id; } } require_once 'sequencinglib.php'; if (scorm_seq_evaluate($sco->id, $usertracks)) { if ($sco->id == $scoid) { $result->prerequisites = true; } $url = $CFG->wwwroot . '/mod/scorm/player.php?a=' . $scorm->id . '&currentorg=' . $currentorg . $modestr . '&scoid=' . $sco->id; $result->toc .= $statusicon . ' ' . $startbold . '<a href="' . $url . '">' . format_string($sco->title) . '</a>' . $score . $endbold . "</li>\n"; $tocmenus[$sco->id] = scorm_repeater('−', $level) . '>' . format_string($sco->title); } else { if ($sco->id == $scoid) { $result->prerequisites = false; } $result->toc .= ' ' . format_string($sco->title) . "</li>\n"; } } } else { $result->toc .= ' ' . format_string($sco->title) . "</li>\n"; } if ($nextsco !== false && $nextid == 0 && $findnext) { if (!empty($nextsco->launch)) { $nextid = $nextsco->id; } } } for ($i = 0; $i < $level; $i++) { $result->toc .= "\t\t</ul></li>\n"; } if ($play) { $sco = $DB->get_record('scorm_scoes', array('id' => $scoid)); $sco->previd = $previd; $sco->nextid = $nextid; $result->sco = $sco; $result->incomplete = $incomplete; } else { $result->incomplete = $incomplete; } } $result->toc .= "\t</ul>\n"; if ($scorm->hidetoc == 0) { $result->toc .= ' <script type="text/javascript"> //<![CDATA[ function expandCollide(which,list,item) { var el = document.ids ? document.ids[list] : document.getElementById ? document.getElementById(list) : document.all[list]; which = which.substring(0,(which.length)); var el2 = document.ids ? document.ids[which] : document.getElementById ? document.getElementById(which) : document.all[which]; if (el.style.display != "none") { el2.src = "' . $scormpixdir . '/plus.gif"; el.style.display=\'none\'; new cookie("hide:SCORMitem" + item, 1, 356, "/").set(); } else { el2.src = "' . $scormpixdir . '/minus.gif"; el.style.display=\'block\'; new cookie("hide:SCORMitem" + item, 1, -1, "/").set(); } } //]]> </script>' . "\n"; } $url = $CFG->wwwroot . '/mod/scorm/player.php?a=' . $scorm->id . '&currentorg=' . $currentorg . $modestr . '&scoid='; $result->tocmenu = popup_form($url, $tocmenus, "tocmenu", $sco->id, '', '', '', true); return $result; }
/** * Retrieves SCO tracking data for the given user id and attempt number * * @param int $scoid the sco id * @param int $userid the user id * @param int $attempt the attempt number * @return array warnings and the scoes data * @since Moodle 3.0 */ public static function get_scorm_sco_tracks($scoid, $userid, $attempt = 0) { global $USER, $DB; $params = self::validate_parameters(self::get_scorm_sco_tracks_parameters(), array('scoid' => $scoid, 'userid' => $userid, 'attempt' => $attempt)); $tracks = 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); // Validate the user obtaining the context, it will fail if the user doesn't exists or have been deleted. context_user::instance($params['userid']); // Extra checks so only users with permissions can view other users attempts. if ($USER->id != $params['userid']) { require_capability('mod/scorm:viewreport', $context); } scorm_require_available($scorm, true, $context); if (empty($params['attempt'])) { $params['attempt'] = scorm_get_last_attempt($scorm->id, $params['userid']); } if ($scormtracks = scorm_get_tracks($sco->id, $params['userid'], $params['attempt'])) { foreach ($scormtracks as $element => $value) { $tracks[] = array( 'element' => $element, 'value' => $value, ); } } $result = array(); $result['data']['attempt'] = $params['attempt']; $result['data']['tracks'] = $tracks; $result['warnings'] = $warnings; return $result; }
function scorm_grade_user($scorm, $userid, $time = false) { // insure we dont grade user beyond $scorm->maxattempt settings $lastattempt = scorm_get_last_attempt($scorm->id, $userid); if ($scorm->maxattempt != 0 && $lastattempt >= $scorm->maxattempt) { $lastattempt = $scorm->maxattempt; } switch ($scorm->whatgrade) { case FIRSTATTEMPT: return scorm_grade_user_attempt($scorm, $userid, 1, $time); break; case LASTATTEMPT: return scorm_grade_user_attempt($scorm, $userid, scorm_get_last_completed_attempt($scorm->id, $userid), $time); break; case HIGHESTATTEMPT: $maxscore = 0; $attempttime = 0; for ($attempt = 1; $attempt <= $lastattempt; $attempt++) { $attemptscore = scorm_grade_user_attempt($scorm, $userid, $attempt, $time); if ($time) { if ($attemptscore->score > $maxscore) { $maxscore = $attemptscore->score; $attempttime = $attemptscore->time; } } else { $maxscore = $attemptscore > $maxscore ? $attemptscore : $maxscore; } } if ($time) { $result = new stdClass(); $result->score = $maxscore; $result->time = $attempttime; return $result; } else { return $maxscore; } break; case AVERAGEATTEMPT: $lastattempt = scorm_get_last_attempt($scorm->id, $userid); $sumscore = 0; for ($attempt = 1; $attempt <= $lastattempt; $attempt++) { $attemptscore = scorm_grade_user_attempt($scorm, $userid, $attempt, $time); if ($time) { $sumscore += $attemptscore->score; } else { $sumscore += $attemptscore; } } if ($lastattempt > 0) { $score = $sumscore / $lastattempt; } else { $score = 0; } if ($time) { $result = new stdClass(); $result->score = $score; $result->time = $attemptscore->time; return $result; } else { return $score; } break; } }
print_header($pagetitle, $course->fullname, $navigation, '', '', true, update_module_button($cm->id, $course->id, $strscorm), '', false); echo $OUTPUT->box(get_string("expired", "scorm", userdate($scorm->timeclose)), "generalbox boxaligncenter"); echo $OUTPUT->footer(); die; } } // // TOC processing // $scorm->version = strtolower(clean_param($scorm->version, PARAM_SAFEDIR)); // Just to be safe if (!file_exists($CFG->dirroot . '/mod/scorm/datamodels/' . $scorm->version . 'lib.php')) { $scorm->version = 'scorm_12'; } require_once $CFG->dirroot . '/mod/scorm/datamodels/' . $scorm->version . 'lib.php'; $attempt = scorm_get_last_attempt($scorm->id, $USER->id); if ($newattempt == 'on' && ($attempt < $scorm->maxattempt || $scorm->maxattempt == 0)) { $attempt++; $mode = 'normal'; } $attemptstr = '&attempt=' . $attempt; $result = scorm_get_toc($USER, $scorm, 'structurelist', $currentorg, $scoid, $mode, $attempt, true); $sco = $result->sco; if ($mode == 'browse' && $scorm->hidebrowse == 1) { $mode = 'normal'; } if ($mode != 'browse') { if ($trackdata = scorm_get_tracks($sco->id, $USER->id, $attempt)) { if ($trackdata->status == 'completed' || $trackdata->status == 'passed' || $trackdata->status == 'failed') { $mode = 'review'; } else {
function scorm_get_toc($user,$scorm,$cmid,$toclink=TOCJSLINK,$currentorg='',$scoid='',$mode='normal',$attempt='',$play=false, $tocheader=false) { global $CFG, $DB, $PAGE, $OUTPUT; $modestr = ''; if ($mode == 'browse') { $modestr = '&mode='.$mode; } $result = new stdClass(); if ($tocheader) { $result->toc = '<div id="scorm_layout">'; $result->toc .= '<div id="scorm_toc">'; $result->toc .= '<div id="scorm_tree">'; } $result->toc .= '<ul>'; $tocmenus = array(); $result->prerequisites = true; $incomplete = false; // // Get the current organization infos // if (!empty($currentorg)) { if (($organizationtitle = $DB->get_field('scorm_scoes', 'title', array('scorm'=>$scorm->id,'identifier'=>$currentorg))) != '') { if ($play) { $result->toctitle = "$organizationtitle"; } else { $result->toc .= "\t<li>$organizationtitle</li>\n"; } $tocmenus[] = $organizationtitle; } } // // If not specified retrieve the last attempt number // if (empty($attempt)) { $attempt = scorm_get_last_attempt($scorm->id, $user->id); } $result->attemptleft = $scorm->maxattempt - $attempt; if ($scoes = scorm_get_scoes($scorm->id, $currentorg)){ // // Retrieve user tracking data for each learning object // $usertracks = array(); foreach ($scoes as $sco) { if (!empty($sco->launch)) { if ($usertrack = scorm_get_tracks($sco->id,$user->id,$attempt)) { if ($usertrack->status == '') { $usertrack->status = 'notattempted'; } $usertracks[$sco->identifier] = $usertrack; } } } $level=0; $sublist=1; $previd = 0; $nextid = 0; $findnext = false; $parents[$level]='/'; foreach ($scoes as $pos => $sco) { $isvisible = false; $sco->title = $sco->title; if (!isset($sco->isvisible) || (isset($sco->isvisible) && ($sco->isvisible == 'true'))) { $isvisible = true; } if ($parents[$level]!=$sco->parent) { if ($newlevel = array_search($sco->parent,$parents)) { for ($i=0; $i<($level-$newlevel); $i++) { $result->toc .= "\t\t</li></ul></li>\n"; } $level = $newlevel; } else { $i = $level; $closelist = ''; while (($i > 0) && ($parents[$level] != $sco->parent)) { $closelist .= "\t\t</li></ul></li>\n"; $i--; } if (($i == 0) && ($sco->parent != $currentorg)) { $result->toc .= "\t\t><ul>\n"; $level++; } else { $result->toc .= $closelist; $level = $i; } $parents[$level]=$sco->parent; } } if ($isvisible) { $result->toc .= "<li>"; } if (isset($scoes[$pos+1])) { $nextsco = $scoes[$pos+1]; } else { $nextsco = false; } $nextisvisible = false; if (!isset($nextsco->isvisible) || (isset($nextsco->isvisible) && ($nextsco->isvisible == 'true'))) { $nextisvisible = true; } if ($nextisvisible && ($nextsco !== false) && ($sco->parent != $nextsco->parent) && (($level==0) || (($level>0) && ($nextsco->parent == $sco->identifier)))) { $sublist++; } if (empty($sco->title)) { $sco->title = $sco->identifier; } if (!empty($sco->launch)) { if ($isvisible) { $score = ''; if (empty($scoid) && ($mode != 'normal')) { $scoid = $sco->id; } if (isset($usertracks[$sco->identifier])) { $usertrack = $usertracks[$sco->identifier]; $strstatus = get_string($usertrack->status,'scorm'); if ($sco->scormtype == 'sco') { $statusicon = '<img src="'.$OUTPUT->pix_url($usertrack->status, 'scorm').'" alt="'.$strstatus.'" title="'.$strstatus.'" />'; } else { $statusicon = '<img src="'.$OUTPUT->pix_url('assetc', 'scorm').'" alt="'.get_string('assetlaunched','scorm').'" title="'.get_string('assetlaunched','scorm').'" />'; } if (($usertrack->status == 'notattempted') || ($usertrack->status == 'incomplete') || ($usertrack->status == 'browsed')) { $incomplete = true; if ($play && empty($scoid)) { $scoid = $sco->id; } } if ($usertrack->score_raw != '' && has_capability('mod/scorm:viewscores', get_context_instance(CONTEXT_MODULE,$cmid))) { $score = '('.get_string('score','scorm').': '.$usertrack->score_raw.')'; } $strsuspended = get_string('suspended','scorm'); if ($incomplete && isset($usertrack->{'cmi.exit'}) && ($usertrack->{'cmi.exit'} == 'suspend')) { $statusicon = '<img src="'.$OUTPUT->pix_url('suspend', 'scorm').'" alt="'.$strstatus.' - '.$strsuspended.'" title="'.$strstatus.' - '.$strsuspended.'" />'; } } else { if ($play && empty($scoid)) { $scoid = $sco->id; } if ($sco->scormtype == 'sco') { $statusicon = '<img src="'.$OUTPUT->pix_url('notattempted', 'scorm').'" alt="'.get_string('notattempted','scorm').'" title="'.get_string('notattempted','scorm').'" />'; $incomplete = true; } else { $statusicon = '<img src="'.$OUTPUT->pix_url('asset', 'scorm').'" alt="'.get_string('asset','scorm').'" title="'.get_string('asset','scorm').'" />'; } } if ($sco->id == $scoid) { $findnext = true; } if (($nextid == 0) && (scorm_count_launchable($scorm->id,$currentorg) > 1) && ($nextsco!==false) && (!$findnext)) { if (!empty($sco->launch)) { $previd = $sco->id; } } require_once($CFG->dirroot.'/mod/scorm/datamodels/sequencinglib.php'); if (scorm_seq_evaluate($sco->id,$usertracks)) { if ($sco->id == $scoid) { $result->prerequisites = true; } if ($toclink == TOCFULLURL) { //display toc with urls for structure page $url = $CFG->wwwroot.'/mod/scorm/player.php?a='.$scorm->id.'&currentorg='.$currentorg.$modestr.'&scoid='.$sco->id; $result->toc .= $statusicon.' <a href="'.$url.'">'.format_string($sco->title).'</a>'.$score."\n"; } else { if ($sco->launch) { $link = 'a='.$scorm->id.'&scoid='.$sco->id.'¤torg='.$currentorg.$modestr.'&attempt='.$attempt; $result->toc .= '<a title="'.$link.'">'.$statusicon.' '.format_string($sco->title).' '.$score.'</a>'; } else { $result->toc .= '<span>'.$statusicon.' '.format_string($sco->title).'</span>'; } } $tocmenus[$sco->id] = scorm_repeater('−',$level) . '>' . format_string($sco->title); } else { if ($sco->id == $scoid) { $result->prerequisites = false; } if ($play) { // should be disabled $result->toc .= '<span>'.$statusicon.' '.format_string($sco->title).'</span>'; } else { $result->toc .= $statusicon.' '.format_string($sco->title)."\n"; } } if (($nextsco === false) || $nextsco->parent == $sco->parent) { $result->toc .= '</li>'; } } } else { $result->toc .= ' '.format_string($sco->title)."</li>\n"; } if (($nextsco !== false) && ($nextid == 0) && ($findnext)) { if (!empty($nextsco->launch)) { $nextid = $nextsco->id; } } } for ($i=0;$i<$level;$i++) { $result->toc .= "\t\t</ul></li>\n"; } if ($play) { $sco = $DB->get_record('scorm_scoes', array('id'=>$scoid)); $sco->previd = $previd; $sco->nextid = $nextid; $result->sco = $sco; $result->incomplete = $incomplete; } else { $result->incomplete = $incomplete; } } $result->toc .= '</ul>'; // NEW IMS TOC if ($tocheader) { $result->toc .= '</div></div></div>'; $result->toc .= '<div id="scorm_navpanel"></div>'; } if ($scorm->hidetoc == 0) { $PAGE->requires->data_for_js('scormdata', array( 'plusicon' => $OUTPUT->pix_url('plus', 'scorm'), 'minusicon' => $OUTPUT->pix_url('minus', 'scorm'))); $PAGE->requires->js('/lib/cookies.js'); $PAGE->requires->js('/mod/scorm/datamodels/scorm_datamodels.js'); } $url = new moodle_url('/mod/scorm/player.php?a='.$scorm->id.'¤torg='.$currentorg.$modestr); $result->tocmenu = $OUTPUT->single_select($url, 'scoid', $tocmenus, $sco->id, null, "tocmenu"); return $result; }
function scorm_get_toc($user, $scorm, $cmid, $toclink = TOCJSLINK, $currentorg = '', $scoid = '', $mode = 'normal', $attempt = '', $play = false, $tocheader = false) { global $CFG, $DB, $OUTPUT; if (empty($attempt)) { $attempt = scorm_get_last_attempt($scorm->id, $user->id); } $result = new stdClass(); $organizationsco = null; if ($tocheader) { $result->toc = "<div id=\"scorm_layout\" class=\"yui3-g-r\">\n"; $result->toc .= "<div id=\"scorm_toc\" class=\"yui3-u-1-5\">\n"; $result->toc .= "<div id=\"scorm_toc_title\"></div>\n"; $result->toc .= "<div id=\"scorm_tree\">\n"; } if (!empty($currentorg)) { $organizationsco = $DB->get_record('scorm_scoes', array('scorm' => $scorm->id, 'identifier' => $currentorg)); if (!empty($organizationsco->title)) { if ($play) { $result->toctitle = $organizationsco->title; } } } $scoes = scorm_get_toc_object($user, $scorm, $currentorg, $scoid, $mode, $attempt, $play, $organizationsco); $treeview = scorm_format_toc_for_treeview($user, $scorm, $scoes['scoes'][0]->children, $scoes['usertracks'], $cmid, $toclink, $currentorg, $attempt, $play, $organizationsco, false); if ($tocheader) { $result->toc .= $treeview->toc; } else { $result->toc = $treeview->toc; } if (!empty($scoes['scoid'])) { $scoid = $scoes['scoid']; } if (empty($scoid)) { $result->sco = $scoes['scoes'][0]->children[0]; } else { $result->sco = scorm_get_sco($scoid); } if ($scorm->hidetoc == SCORM_TOC_POPUP) { $tocmenu = scorm_format_toc_for_droplist($scorm, $scoes['scoes'][0]->children, $scoes['usertracks'], $currentorg, $organizationsco); $modestr = ''; if ($mode != 'normal') { $modestr = '&mode=' . $mode; } $url = new moodle_url('/mod/scorm/player.php?a=' . $scorm->id . '¤torg=' . $currentorg . $modestr); $result->tocmenu = $OUTPUT->single_select($url, 'scoid', $tocmenu, $result->sco->id, null, "tocmenu"); } $result->prerequisites = $treeview->prerequisites; $result->incomplete = $treeview->incomplete; $result->attemptleft = $treeview->attemptleft; if ($tocheader) { $result->toc .= "</div></div>\n"; $result->toc .= "<div id=\"scorm_toc_toggle\">\n"; $result->toc .= "<button id=\"scorm_toc_toggle_btn\"></button></div>\n"; $result->toc .= "<div id=\"scorm_content\">"; $result->toc .= "<div id=\"scorm_navpanel\"></div>\n"; $result->toc .= "</div></div>\n"; } return $result; }
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; }