mirror of
https://github.com/moodle/moodle.git
synced 2025-01-20 15:08:32 +01:00
1149 lines
44 KiB
PHP
1149 lines
44 KiB
PHP
<?php
|
|
/// mnielsen @ CDC
|
|
/// locallib.php is the new lib file for lesson module.
|
|
/// including locallib.php is the same as including the old lib.php
|
|
|
|
if (!defined("LESSON_UNSEENPAGE")) {
|
|
define("LESSON_UNSEENPAGE", 1); // Next page -> any page not seen before
|
|
}
|
|
if (!defined("LESSON_UNANSWEREDPAGE")) {
|
|
define("LESSON_UNANSWEREDPAGE", 2); // Next page -> any page not answered correctly
|
|
}
|
|
|
|
$LESSON_NEXTPAGE_ACTION = array (0 => get_string("normal", "lesson"),
|
|
LESSON_UNSEENPAGE => get_string("showanunseenpage", "lesson"),
|
|
LESSON_UNANSWEREDPAGE => get_string("showanunansweredpage", "lesson") );
|
|
|
|
|
|
if (!defined("LESSON_NEXTPAGE")) {
|
|
define("LESSON_NEXTPAGE", -1); // Next page
|
|
}
|
|
if (!defined("LESSON_EOL")) {
|
|
define("LESSON_EOL", -9); // End of Lesson
|
|
}
|
|
/// CDC-FLAG 6/14/04 ///
|
|
if (!defined("LESSON_UNSEENBRANCHPAGE")) {
|
|
define("LESSON_UNSEENBRANCHPAGE", -50); // Unseen branch page
|
|
}
|
|
if (!defined("LESSON_PREVIOUSPAGE")) {
|
|
define("LESSON_PREVIOUSPAGE", -40); // previous page
|
|
}
|
|
if (!defined("LESSON_RANDOMPAGE")) {
|
|
define("LESSON_RANDOMPAGE", -60); // random branch page
|
|
}
|
|
if (!defined("LESSON_RANDOMBRANCH")) {
|
|
define("LESSON_RANDOMBRANCH", -70); // random branch
|
|
}
|
|
if (!defined("LESSON_CLUSTERJUMP")) {
|
|
define("LESSON_CLUSTERJUMP", -80); // random within a cluster
|
|
}
|
|
/// CDC-FLAG ///
|
|
if (!defined("LESSON_UNDEFINED")) {
|
|
define("LESSON_UNDEFINED", -99); // undefined
|
|
}
|
|
|
|
if (!defined("LESSON_SHORTANSWER")) {
|
|
define("LESSON_SHORTANSWER", "1");
|
|
}
|
|
if (!defined("LESSON_TRUEFALSE")) {
|
|
define("LESSON_TRUEFALSE", "2");
|
|
}
|
|
if (!defined("LESSON_MULTICHOICE")) { // if you change the value of this (WHICH YOU SHOULDNT) then you need to change it in restorelib.php as well
|
|
define("LESSON_MULTICHOICE", "3");
|
|
}
|
|
if (!defined("LESSON_RANDOM")) {
|
|
define("LESSON_RANDOM", "4");
|
|
}
|
|
if (!defined("LESSON_MATCHING")) { // if you change the value of this (WHICH YOU SHOULDNT) then you need to change it in restorelib.php as well
|
|
define("LESSON_MATCHING", "5");
|
|
}
|
|
if (!defined("LESSON_RANDOMSAMATCH")) {
|
|
define("LESSON_RANDOMSAMATCH", "6");
|
|
}
|
|
if (!defined("LESSON_DESCRIPTION")) {
|
|
define("LESSON_DESCRIPTION", "7");
|
|
}
|
|
if (!defined("LESSON_NUMERICAL")) {
|
|
define("LESSON_NUMERICAL", "8");
|
|
}
|
|
if (!defined("LESSON_MULTIANSWER")) {
|
|
define("LESSON_MULTIANSWER", "9");
|
|
}
|
|
/// CDC-FLAG /// 6/16/04
|
|
if (!defined("LESSON_ESSAY")) {
|
|
define("LESSON_ESSAY", "10");
|
|
}
|
|
if (!defined("LESSON_CLUSTER")) {
|
|
define("LESSON_CLUSTER", "30");
|
|
}
|
|
if (!defined("LESSON_ENDOFCLUSTER")) {
|
|
define("LESSON_ENDOFCLUSTER", "31");
|
|
}
|
|
/// CDC-FLAG ///
|
|
|
|
$LESSON_QUESTION_TYPE = array ( LESSON_MULTICHOICE => get_string("multichoice", "quiz"),
|
|
LESSON_TRUEFALSE => get_string("truefalse", "quiz"),
|
|
LESSON_SHORTANSWER => get_string("shortanswer", "quiz"),
|
|
LESSON_NUMERICAL => get_string("numerical", "quiz"),
|
|
LESSON_MATCHING => get_string("match", "quiz"),
|
|
LESSON_ESSAY => get_string("essay", "lesson") /// CDC-FLAG 6/16/04
|
|
// LESSON_DESCRIPTION => get_string("description", "quiz"),
|
|
// LESSON_RANDOM => get_string("random", "quiz"),
|
|
// LESSON_RANDOMSAMATCH => get_string("randomsamatch", "quiz"),
|
|
// LESSON_MULTIANSWER => get_string("multianswer", "quiz"),
|
|
);
|
|
|
|
if (!defined("LESSON_BRANCHTABLE")) {
|
|
define("LESSON_BRANCHTABLE", "20");
|
|
}
|
|
if (!defined("LESSON_ENDOFBRANCH")) {
|
|
define("LESSON_ENDOFBRANCH", "21");
|
|
}
|
|
|
|
if (!defined("LESSON_ANSWER_EDITOR")) {
|
|
define("LESSON_ANSWER_EDITOR", "1");
|
|
}
|
|
if (!defined("LESSON_RESPONSE_EDITOR")) {
|
|
define("LESSON_RESPONSE_EDITOR", "2");
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
/// Any other lesson functions go here. Each of them must have a name that
|
|
/// starts with lesson_
|
|
|
|
/*******************************************************************/
|
|
function lesson_save_question_options($question) {
|
|
/// Given some question info and some data about the the answers
|
|
/// this function parses, organises and saves the question
|
|
/// This is only used when IMPORTING questions and is only called
|
|
/// from format.php
|
|
/// Lifted from mod/quiz/lib.php -
|
|
/// 1. all reference to oldanswers removed
|
|
/// 2. all reference to quiz_multichoice table removed
|
|
/// 3. In SHORTANSWER questions usecase is store in the qoption field
|
|
/// 4. In NUMERIC questions store the range as two answers
|
|
/// 5. TRUEFALSE options are ignored
|
|
/// 6. For MULTICHOICE questions with more than one answer the qoption field is true
|
|
///
|
|
/// Returns $result->error or $result->notice
|
|
|
|
$timenow = time();
|
|
switch ($question->qtype) {
|
|
case LESSON_SHORTANSWER:
|
|
|
|
$answers = array();
|
|
$maxfraction = -1;
|
|
|
|
// Insert all the new answers
|
|
foreach ($question->answer as $key => $dataanswer) {
|
|
if ($dataanswer != "") {
|
|
$answer = new stdClass;
|
|
$answer->lessonid = $question->lessonid;
|
|
$answer->pageid = $question->id;
|
|
if ($question->fraction[$key] >=0.5) {
|
|
$answer->jumpto = LESSON_NEXTPAGE;
|
|
}
|
|
$answer->timecreated = $timenow;
|
|
$answer->grade = $question->fraction[$key] * 100;
|
|
$answer->answer = $dataanswer;
|
|
$answer->feedback = $question->feedback[$key];
|
|
if (!$answer->id = insert_record("lesson_answers", $answer)) {
|
|
$result->error = "Could not insert shortanswer quiz answer!";
|
|
return $result;
|
|
}
|
|
$answers[] = $answer->id;
|
|
if ($question->fraction[$key] > $maxfraction) {
|
|
$maxfraction = $question->fraction[$key];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// Perform sanity checks on fractional grades
|
|
if ($maxfraction != 1) {
|
|
$maxfraction = $maxfraction * 100;
|
|
$result->notice = get_string("fractionsnomax", "quiz", $maxfraction);
|
|
return $result;
|
|
}
|
|
break;
|
|
|
|
case LESSON_NUMERICAL: // Note similarities to SHORTANSWER
|
|
|
|
$answers = array();
|
|
$maxfraction = -1;
|
|
|
|
|
|
// for each answer store the pair of min and max values even if they are the same
|
|
foreach ($question->answer as $key => $dataanswer) {
|
|
if ($dataanswer != "") {
|
|
$answer = new stdClass;
|
|
$answer->lessonid = $question->lessonid;
|
|
$answer->pageid = $question->id;
|
|
$answer->jumpto = LESSON_NEXTPAGE;
|
|
$answer->timecreated = $timenow;
|
|
$answer->grade = $question->fraction[$key] * 100;
|
|
$answer->answer = $question->min[$key].":".$question->max[$key];
|
|
$answer->response = $question->feedback[$key];
|
|
if (!$answer->id = insert_record("lesson_answers", $answer)) {
|
|
$result->error = "Could not insert numerical quiz answer!";
|
|
return $result;
|
|
}
|
|
|
|
$answers[] = $answer->id;
|
|
if ($question->fraction[$key] > $maxfraction) {
|
|
$maxfraction = $question->fraction[$key];
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Perform sanity checks on fractional grades
|
|
if ($maxfraction != 1) {
|
|
$maxfraction = $maxfraction * 100;
|
|
$result->notice = get_string("fractionsnomax", "quiz", $maxfraction);
|
|
return $result;
|
|
}
|
|
break;
|
|
|
|
|
|
case LESSON_TRUEFALSE:
|
|
|
|
// the truth
|
|
$answer->lessonid = $question->lessonid;
|
|
$answer->pageid = $question->id;
|
|
$answer->timecreated = $timenow;
|
|
$answer->answer = get_string("true", "quiz");
|
|
$answer->grade = $question->answer * 100;
|
|
if ($answer->grade > 50 ) {
|
|
$answer->jumpto = LESSON_NEXTPAGE;
|
|
}
|
|
if (isset($question->feedbacktrue)) {
|
|
$answer->response = $question->feedbacktrue;
|
|
}
|
|
if (!$true->id = insert_record("lesson_answers", $answer)) {
|
|
$result->error = "Could not insert quiz answer \"true\")!";
|
|
return $result;
|
|
}
|
|
|
|
// the lie
|
|
$answer = new stdClass;
|
|
$answer->lessonid = $question->lessonid;
|
|
$answer->pageid = $question->id;
|
|
$answer->timecreated = $timenow;
|
|
$answer->answer = get_string("false", "quiz");
|
|
$answer->grade = (1 - (int)$question->answer) * 100;
|
|
if ($answer->grade > 50 ) {
|
|
$answer->jumpto = LESSON_NEXTPAGE;
|
|
}
|
|
if (isset($question->feedbackfalse)) {
|
|
$answer->response = $question->feedbackfalse;
|
|
}
|
|
if (!$false->id = insert_record("lesson_answers", $answer)) {
|
|
$result->error = "Could not insert quiz answer \"false\")!";
|
|
return $result;
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case LESSON_MULTICHOICE:
|
|
|
|
$totalfraction = 0;
|
|
$maxfraction = -1;
|
|
|
|
$answers = array();
|
|
|
|
// Insert all the new answers
|
|
foreach ($question->answer as $key => $dataanswer) {
|
|
if ($dataanswer != "") {
|
|
$answer = new stdClass;
|
|
$answer->lessonid = $question->lessonid;
|
|
$answer->pageid = $question->id;
|
|
$answer->timecreated = $timenow;
|
|
$answer->grade = $question->fraction[$key] * 100;
|
|
/// CDC-FLAG changed some defaults
|
|
/* Original Code
|
|
if ($answer->grade > 50 ) {
|
|
$answer->jumpto = LESSON_NEXTPAGE;
|
|
}
|
|
Replaced with: */
|
|
if ($answer->grade > 50 ) {
|
|
$answer->jumpto = LESSON_NEXTPAGE;
|
|
$answer->score = 1;
|
|
}
|
|
// end Replace
|
|
$answer->answer = $dataanswer;
|
|
$answer->response = $question->feedback[$key];
|
|
if (!$answer->id = insert_record("lesson_answers", $answer)) {
|
|
$result->error = "Could not insert multichoice quiz answer! ";
|
|
return $result;
|
|
}
|
|
// for Sanity checks
|
|
if ($question->fraction[$key] > 0) {
|
|
$totalfraction += $question->fraction[$key];
|
|
}
|
|
if ($question->fraction[$key] > $maxfraction) {
|
|
$maxfraction = $question->fraction[$key];
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Perform sanity checks on fractional grades
|
|
if ($question->single) {
|
|
if ($maxfraction != 1) {
|
|
$maxfraction = $maxfraction * 100;
|
|
$result->notice = get_string("fractionsnomax", "quiz", $maxfraction);
|
|
return $result;
|
|
}
|
|
} else {
|
|
$totalfraction = round($totalfraction,2);
|
|
if ($totalfraction != 1) {
|
|
$totalfraction = $totalfraction * 100;
|
|
$result->notice = get_string("fractionsaddwrong", "quiz", $totalfraction);
|
|
return $result;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LESSON_MATCHING:
|
|
|
|
$subquestions = array();
|
|
|
|
$i = 0;
|
|
// Insert all the new question+answer pairs
|
|
foreach ($question->subquestions as $key => $questiontext) {
|
|
$answertext = $question->subanswers[$key]; echo $answertext; echo "<br>"; exit;
|
|
if (!empty($questiontext) and !empty($answertext)) {
|
|
$answer = new stdClass;
|
|
$answer->lessonid = $question->lessonid;
|
|
$answer->pageid = $question->id;
|
|
$answer->timecreated = $timenow;
|
|
$answer->answer = $questiontext;
|
|
$answer->response = $answertext;
|
|
if ($i == 0) {
|
|
// first answer contains the correct answer jump
|
|
$answer->jumpto = LESSON_NEXTPAGE;
|
|
}
|
|
if (!$subquestion->id = insert_record("lesson_answers", $answer)) {
|
|
$result->error = "Could not insert quiz match subquestion!";
|
|
return $result;
|
|
}
|
|
$subquestions[] = $subquestion->id;
|
|
$i++;
|
|
}
|
|
}
|
|
|
|
if (count($subquestions) < 3) {
|
|
$result->notice = get_string("notenoughsubquestions", "quiz");
|
|
return $result;
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case LESSON_RANDOMSAMATCH:
|
|
$options->question = $question->id;
|
|
$options->choose = $question->choose;
|
|
if ($existing = get_record("quiz_randomsamatch", "question", $options->question)) {
|
|
$options->id = $existing->id;
|
|
if (!update_record("quiz_randomsamatch", $options)) {
|
|
$result->error = "Could not update quiz randomsamatch options!";
|
|
return $result;
|
|
}
|
|
} else {
|
|
if (!insert_record("quiz_randomsamatch", $options)) {
|
|
$result->error = "Could not insert quiz randomsamatch options!";
|
|
return $result;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LESSON_MULTIANSWER:
|
|
if (!$oldmultianswers = get_records("quiz_multianswers", "question", $question->id, "id ASC")) {
|
|
$oldmultianswers = array();
|
|
}
|
|
|
|
// Insert all the new multi answers
|
|
foreach ($question->answers as $dataanswer) {
|
|
if ($oldmultianswer = array_shift($oldmultianswers)) { // Existing answer, so reuse it
|
|
$multianswer = $oldmultianswer;
|
|
$multianswer->positionkey = $dataanswer->positionkey;
|
|
$multianswer->norm = $dataanswer->norm;
|
|
$multianswer->answertype = $dataanswer->answertype;
|
|
|
|
if (! $multianswer->answers = quiz_save_multianswer_alternatives
|
|
($question->id, $dataanswer->answertype,
|
|
$dataanswer->alternatives, $oldmultianswer->answers))
|
|
{
|
|
$result->error = "Could not update multianswer alternatives! (id=$multianswer->id)";
|
|
return $result;
|
|
}
|
|
if (!update_record("quiz_multianswers", $multianswer)) {
|
|
$result->error = "Could not update quiz multianswer! (id=$multianswer->id)";
|
|
return $result;
|
|
}
|
|
} else { // This is a completely new answer
|
|
$multianswer = new stdClass;
|
|
$multianswer->question = $question->id;
|
|
$multianswer->positionkey = $dataanswer->positionkey;
|
|
$multianswer->norm = $dataanswer->norm;
|
|
$multianswer->answertype = $dataanswer->answertype;
|
|
|
|
if (! $multianswer->answers = quiz_save_multianswer_alternatives
|
|
($question->id, $dataanswer->answertype,
|
|
$dataanswer->alternatives))
|
|
{
|
|
$result->error = "Could not insert multianswer alternatives! (questionid=$question->id)";
|
|
return $result;
|
|
}
|
|
if (!insert_record("quiz_multianswers", $multianswer)) {
|
|
$result->error = "Could not insert quiz multianswer!";
|
|
return $result;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LESSON_RANDOM:
|
|
break;
|
|
|
|
case LESSON_DESCRIPTION:
|
|
break;
|
|
|
|
default:
|
|
$result->error = "Unsupported question type ($question->qtype)!";
|
|
return $result;
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
/*******************************************************************/
|
|
function lesson_choose_from_menu ($options, $name, $selected="", $nothing="choose", $script="", $nothingvalue="0", $return=false) {
|
|
/// Given an array of value, creates a popup menu to be part of a form
|
|
/// $options["value"]["label"]
|
|
|
|
if ($nothing == "choose") {
|
|
$nothing = get_string("choose")."...";
|
|
}
|
|
|
|
if ($script) {
|
|
$javascript = "onChange=\"$script\"";
|
|
} else {
|
|
$javascript = "";
|
|
}
|
|
|
|
$output = "<label for=$name class=hidden-label>$name</label><SELECT id=$name NAME=$name $javascript>\n"; //CDC hidden label added.
|
|
if ($nothing) {
|
|
$output .= " <OPTION VALUE=\"$nothingvalue\"\n";
|
|
if ($nothingvalue == $selected) {
|
|
$output .= " SELECTED";
|
|
}
|
|
$output .= ">$nothing</OPTION>\n";
|
|
}
|
|
if (!empty($options)) {
|
|
foreach ($options as $value => $label) {
|
|
$output .= " <OPTION VALUE=\"$value\"";
|
|
if ($value == $selected) {
|
|
$output .= " SELECTED";
|
|
}
|
|
// stop zero label being replaced by array index value
|
|
// if ($label) {
|
|
// $output .= ">$label</OPTION>\n";
|
|
// } else {
|
|
// $output .= ">$value</OPTION>\n";
|
|
// }
|
|
$output .= ">$label</OPTION>\n";
|
|
|
|
}
|
|
}
|
|
$output .= "</SELECT>\n";
|
|
|
|
if ($return) {
|
|
return $output;
|
|
} else {
|
|
echo $output;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_iscorrect($pageid, $jumpto) {
|
|
// returns true is jumpto page is (logically) after the pageid page, other returns false
|
|
|
|
// first test the special values
|
|
if (!$jumpto) {
|
|
// same page
|
|
return false;
|
|
} elseif ($jumpto == LESSON_NEXTPAGE) {
|
|
return true;
|
|
/// CDC-FLAG 6/21/04 ///
|
|
} elseif ($jumpto == LESSON_UNSEENBRANCHPAGE) {
|
|
return true;
|
|
} elseif ($jumpto == LESSON_RANDOMPAGE) {
|
|
return true;
|
|
} elseif ($jumpto == LESSON_CLUSTERJUMP) {
|
|
return true;
|
|
/// CDC-FLAG ///
|
|
} elseif ($jumpto == LESSON_EOL) {
|
|
return true;
|
|
}
|
|
// we have to run through the pages from pageid looking for jumpid
|
|
$apageid = get_field("lesson_pages", "nextpageid", "id", $pageid);
|
|
while (true) {
|
|
if ($jumpto == $apageid) {
|
|
return true;
|
|
}
|
|
if ($apageid) {
|
|
$apageid = get_field("lesson_pages", "nextpageid", "id", $apageid);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
return false; // should never be reached
|
|
}
|
|
|
|
/// CDC-FLAG ///
|
|
/*******************************************************************/
|
|
function lesson_display_branch_jumps($lesson_id, $pageid) {
|
|
// this fucntion checks to see if a page is a branch or is
|
|
// a page that is enclosed by a branch table and an endofbranch/eol
|
|
|
|
// NoticeFix ... this may cause problems... not sure
|
|
if($pageid == 0) {
|
|
// first page
|
|
return false;
|
|
}
|
|
// get all of the lesson pages
|
|
if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson_id")) {
|
|
// adding first page
|
|
return false;
|
|
}
|
|
|
|
if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
|
|
return true;
|
|
}
|
|
|
|
return lesson_is_page_in_branch($lessonpages, $pageid);
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_display_cluster_jump($lesson_id, $pageid) {
|
|
// this fucntion checks to see if a page is a cluster page or is
|
|
// a page that is enclosed by a cluster page and an endofcluster/eol
|
|
|
|
// NoticeFix ... this may cause problems... not sure
|
|
if($pageid == 0) {
|
|
// first page
|
|
return false;
|
|
}
|
|
// get all of the lesson pages
|
|
if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson_id")) {
|
|
// adding first page
|
|
return false;
|
|
}
|
|
|
|
if ($lessonpages[$pageid]->qtype == LESSON_CLUSTER) {
|
|
return true;
|
|
}
|
|
|
|
return lesson_is_page_in_cluster($lessonpages, $pageid);
|
|
|
|
}
|
|
|
|
// 6/21/04
|
|
/*******************************************************************/
|
|
function execute_teacherwarning($lesson) {
|
|
// this function checks to see if a LESSON_CLUSTERJUMP or
|
|
// a LESSON_UNSEENBRANCHPAGE is used in a lesson.
|
|
// This function is only executed when a teacher is
|
|
// checking the navigation for a lesson.
|
|
|
|
// get all of the lesson answers
|
|
if (!$lessonanswers = get_records_select("lesson_answers", "lessonid = $lesson")) {
|
|
// no answers, then not useing cluster or unseen
|
|
return false;
|
|
}
|
|
// just check for the first one that fulfills the requirements
|
|
foreach ($lessonanswers as $lessonanswer) {
|
|
if ($lessonanswer->jumpto == LESSON_CLUSTERJUMP || $lessonanswer->jumpto == LESSON_UNSEENBRANCHPAGE) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// if no answers use either of the two jumps
|
|
return false;
|
|
}
|
|
|
|
|
|
// 6/18/04
|
|
/*******************************************************************/
|
|
function lesson_cluster_jump($lesson, $user, $pageid) {
|
|
// this fucntion interprets LESSON_CLUSTERJUMP
|
|
// it will select a page randomly
|
|
// and the page selected will be inbetween a cluster page and endofcluter/eol
|
|
// and the page selected will be a page that has not been viewed already
|
|
// and if any pages are within a branchtable/endofbranch then only 1 page within
|
|
// the branchtable/endofbranch will be randomly selected (sub clustering)
|
|
|
|
// get the number of retakes
|
|
if (!$retakes = count_records("lesson_grades", "lessonid", $lesson, "userid", $user)) {
|
|
$retakes = 0;
|
|
}
|
|
|
|
// get all the lesson_attempts aka what the user has seen
|
|
if ($seen = get_records_select("lesson_attempts", "lessonid = $lesson AND userid = $user AND retry = $retakes", "timeseen DESC")) {
|
|
foreach ($seen as $value) { // load it into an array that I can more easily use
|
|
$seenpages[$value->pageid] = $value->pageid;
|
|
}
|
|
} else {
|
|
$seenpages = array();
|
|
}
|
|
|
|
// get the lesson pages
|
|
if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson")) {
|
|
error("Error: could not find records in lesson_pages table");
|
|
}
|
|
// find the start of the cluster
|
|
while ($pageid != 0) { // this condition should not be satisfied... should be a cluster page
|
|
if ($lessonpages[$pageid]->qtype == LESSON_CLUSTER) {
|
|
break;
|
|
}
|
|
$pageid = $lessonpages[$pageid]->prevpageid;
|
|
}
|
|
|
|
$pageid = $lessonpages[$pageid]->nextpageid; // move down from the cluster page
|
|
|
|
$clusterpages = array();
|
|
while (true) { // now load all the pages into the cluster that are not already inside of a branch table.
|
|
if ($lessonpages[$pageid]->qtype == LESSON_ENDOFCLUSTER) {
|
|
// store the endofcluster page's jump
|
|
$exitjump = get_field("lesson_answers", "jumpto", "pageid", $pageid, "lessonid", $lesson);
|
|
if ($exitjump == LESSON_NEXTPAGE) {
|
|
$exitjump = $lessonpages[$pageid]->nextpageid;
|
|
}
|
|
if ($exitjump == 0) {
|
|
$exitjump = LESSON_EOL;
|
|
}
|
|
break;
|
|
} elseif (!lesson_is_page_in_branch($lessonpages, $pageid) && $lessonpages[$pageid]->qtype != LESSON_ENDOFBRANCH) {
|
|
// load page into array when it is not in a branch table and when it is not an endofbranch
|
|
$clusterpages[] = $lessonpages[$pageid];
|
|
}
|
|
if ($lessonpages[$pageid]->nextpageid == 0) {
|
|
// shouldn't ever get here... should be using endofcluster
|
|
$exitjump = LESSON_EOL;
|
|
break;
|
|
} else {
|
|
$pageid = $lessonpages[$pageid]->nextpageid;
|
|
}
|
|
}
|
|
|
|
// filter out the ones we have seen
|
|
$unseen = array();
|
|
foreach ($clusterpages as $clusterpage) {
|
|
if ($clusterpage->qtype == LESSON_BRANCHTABLE) { // if branchtable, check to see if any pages inside have been viewed
|
|
$branchpages = lesson_pages_in_branch($lessonpages, $clusterpage->id); // get the pages in the branchtable
|
|
$flag = true;
|
|
foreach ($branchpages as $branchpage) {
|
|
if (array_key_exists($branchpage->id, $seenpages)) { // check if any of the pages have been viewed
|
|
$flag = false;
|
|
}
|
|
}
|
|
if ($flag && count($branchpages) > 0) {
|
|
// add branch table
|
|
$unseen[] = $clusterpage;
|
|
}
|
|
} else {
|
|
// add any other type of page that has not already been viewed
|
|
if (!array_key_exists($clusterpage->id, $seenpages)) {
|
|
$unseen[] = $clusterpage;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (count($unseen) > 0) { // it does not contain elements, then use exitjump, otherwise find out next page/branch
|
|
$nextpage = $unseen[rand(0, count($unseen)-1)];
|
|
} else {
|
|
return $exitjump; // seen all there is to see, leave the cluster
|
|
}
|
|
|
|
if ($nextpage->qtype == LESSON_BRANCHTABLE) { // if branch table, then pick a random page inside of it
|
|
$branchpages = lesson_pages_in_branch($lessonpages, $nextpage->id);
|
|
return $branchpages[rand(0, count($branchpages)-1)]->id;
|
|
} else { // otherwise, return the page's id
|
|
return $nextpage->id;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_pages_in_branch($lessonpages, $branchid) {
|
|
// returns pages that are within a branch
|
|
|
|
$pageid = $lessonpages[$branchid]->nextpageid; // move to the first page after the branch table
|
|
$pagesinbranch = array();
|
|
|
|
while (true) {
|
|
if ($pageid == 0) { // EOL
|
|
break;
|
|
} elseif ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
|
|
break;
|
|
} elseif ($lessonpages[$pageid]->qtype == LESSON_ENDOFBRANCH) {
|
|
break;
|
|
}
|
|
$pagesinbranch[] = $lessonpages[$pageid];
|
|
$pageid = $lessonpages[$pageid]->nextpageid;
|
|
}
|
|
|
|
return $pagesinbranch;
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_unseen_question_jump($lesson, $user, $pageid) {
|
|
// This function interprets the LESSON_UNSEENBRANCHPAGE jump.
|
|
// will return the pageid of a random unseen page that is within a branch
|
|
|
|
// get the number of retakes
|
|
if (!$retakes = count_records("lesson_grades", "lessonid", $lesson, "userid", $user)) {
|
|
$retakes = 0;
|
|
}
|
|
|
|
// get all the lesson_attempts aka what the user has seen
|
|
if ($viewedpages = get_records_select("lesson_attempts", "lessonid = $lesson AND userid = $user AND retry = $retakes", "timeseen DESC")) {
|
|
foreach($viewedpages as $viewed) {
|
|
$seenpages[] = $viewed->pageid;
|
|
}
|
|
} else {
|
|
$seenpages = array();
|
|
}
|
|
|
|
// get the lesson pages
|
|
if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson")) {
|
|
error("Error: could not find records in lesson_pages table");
|
|
}
|
|
|
|
if ($pageid == LESSON_UNSEENBRANCHPAGE) { // this only happens when a student leaves in the middle of an unseen question within a branch series
|
|
$pageid = $seenpages[0]; // just change the pageid to the last page viewed inside the branch table
|
|
}
|
|
|
|
// go up the pages till branch table
|
|
while ($pageid != 0) { // this condition should never be satisfied... only happens if there are no branch tables above this page
|
|
if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
|
|
break;
|
|
}
|
|
$pageid = $lessonpages[$pageid]->prevpageid;
|
|
}
|
|
|
|
$pagesinbranch = lesson_pages_in_branch($lessonpages, $pageid);
|
|
|
|
// this foreach loop stores all the pages that are within the branch table but are not in the $seenpages array
|
|
$unseen = array();
|
|
foreach($pagesinbranch as $page) {
|
|
if (!in_array($page->id, $seenpages)) {
|
|
$unseen[] = $page->id;
|
|
}
|
|
}
|
|
|
|
if(count($unseen) == 0) {
|
|
if(isset($pagesinbranch)) {
|
|
$temp = end($pagesinbranch);
|
|
$nextpage = $temp->nextpageid; // they have seen all the pages in the branch, so go to EOB/next branch table/EOL
|
|
} else {
|
|
// there are no pages inside the branch, so return the next page
|
|
$nextpage = $lessonpages[$pageid]->nextpageid;
|
|
}
|
|
if ($nextpage == 0) {
|
|
return LESSON_EOL;
|
|
} else {
|
|
return $nextpage;
|
|
}
|
|
} else {
|
|
return $unseen[rand(0, count($unseen)-1)]; // returns a random page id for the next page
|
|
}
|
|
}
|
|
|
|
// 6/15/04
|
|
/*******************************************************************/
|
|
function lesson_unseen_branch_jump($lesson, $user) {
|
|
// This will return a random unseen branch table
|
|
|
|
if (!$retakes = count_records("lesson_grades", "lessonid", $lesson, "userid", $user)) {
|
|
$retakes = 0;
|
|
}
|
|
|
|
if (!$seenbranches = get_records_select("lesson_branch", "lessonid = $lesson AND userid = $user AND retry = $retakes",
|
|
"timeseen DESC")) {
|
|
error("Error: could not find records in lesson_branch table");
|
|
}
|
|
|
|
// get the lesson pages
|
|
if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson")) {
|
|
error("Error: could not find records in lesson_pages table");
|
|
}
|
|
|
|
// this loads all the viewed branch tables into $seen untill it finds the branch table with the flag
|
|
// which is the branch table that starts the unseenbranch function
|
|
$seen = array();
|
|
foreach ($seenbranches as $seenbranch) {
|
|
if (!$seenbranch->flag) {
|
|
$seen[$seenbranch->pageid] = $seenbranch->pageid;
|
|
} else {
|
|
$start = $seenbranch->pageid;
|
|
break;
|
|
}
|
|
}
|
|
// this function searches through the lesson pages to find all the branch tables
|
|
// that follow the flagged branch table
|
|
$pageid = $lessonpages[$start]->nextpageid; // move down from the flagged branch table
|
|
while ($pageid != 0) { // grab all of the branch table till eol
|
|
if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
|
|
$branchtables[] = $lessonpages[$pageid]->id;
|
|
}
|
|
$pageid = $lessonpages[$pageid]->nextpageid;
|
|
}
|
|
$unseen = array();
|
|
foreach ($branchtables as $branchtable) {
|
|
// load all of the unseen branch tables into unseen
|
|
if (!array_key_exists($branchtable, $seen)) {
|
|
$unseen[] = $branchtable;
|
|
}
|
|
}
|
|
if (count($unseen) > 0) {
|
|
return $unseen[rand(0, count($unseen)-1)]; // returns a random page id for the next page
|
|
} else {
|
|
return LESSON_EOL; // has viewed all of the branch tables
|
|
}
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_random_question_jump($lesson, $pageid) {
|
|
// This function will return the pageid of a random page
|
|
// that is within a branch table
|
|
|
|
// get the lesson pages
|
|
if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson")) {
|
|
error("Error: could not find records in lesson_pages table");
|
|
}
|
|
|
|
// go up the pages till branch table
|
|
while ($pageid != 0) { // this condition should never be satisfied... only happens if there are no branch tables above this page
|
|
|
|
if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
|
|
break;
|
|
}
|
|
$pageid = $lessonpages[$pageid]->prevpageid;
|
|
}
|
|
|
|
// get the pages within the branch
|
|
$pagesinbranch = lesson_pages_in_branch($lessonpages, $pageid);
|
|
|
|
if(count($pagesinbranch) == 0) {
|
|
// there are no pages inside the branch, so return the next page
|
|
return $lessonpages[$pageid]->nextpageid;
|
|
} else {
|
|
return $pagesinbranch[rand(0, count($pagesinbranch)-1)]->id; // returns a random page id for the next page
|
|
}
|
|
}
|
|
|
|
// 6/15/04
|
|
/*******************************************************************/
|
|
function lesson_is_page_in_branch($pages, $pageid) {
|
|
// This function's purpose is to check if a page is within a branch or not
|
|
|
|
$pageid = $pages[$pageid]->prevpageid; // move up one
|
|
|
|
// go up the pages till branch table
|
|
while (true) {
|
|
if ($pageid == 0) { // ran into the beginning of the lesson
|
|
return false;
|
|
} elseif ($pages[$pageid]->qtype == LESSON_ENDOFBRANCH) { // ran into the end of another branch table
|
|
return false;
|
|
} elseif ($pages[$pageid]->qtype == LESSON_CLUSTER) { // do not look beyond a cluster
|
|
return false;
|
|
} elseif ($pages[$pageid]->qtype == LESSON_BRANCHTABLE) { // hit a branch table
|
|
return true;
|
|
}
|
|
$pageid = $pages[$pageid]->prevpageid;
|
|
}
|
|
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_is_page_in_cluster($pages, $pageid) {
|
|
// This function checks to see if a page is within a cluster or not
|
|
|
|
$pageid = $pages[$pageid]->prevpageid; // move up one
|
|
|
|
// go up the pages till branch table
|
|
while (true) {
|
|
if ($pageid == 0) { // ran into the beginning of the lesson
|
|
return false;
|
|
} elseif ($pages[$pageid]->qtype == LESSON_ENDOFCLUSTER) { // ran into the end of another branch table
|
|
return false;
|
|
} elseif ($pages[$pageid]->qtype == LESSON_CLUSTER) { // hit a branch table
|
|
return true;
|
|
}
|
|
$pageid = $pages[$pageid]->prevpageid;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_print_tree_menu($lessonid, $pageid, $id, $showpages=false) {
|
|
// prints the contents of the left menu
|
|
|
|
if(!$pages = get_records_select("lesson_pages", "lessonid = $lessonid")) {
|
|
error("Error: could not find lesson pages");
|
|
}
|
|
while ($pageid != 0) {
|
|
lesson_print_tree_link_menu($pages[$pageid], $id, true);
|
|
$pageid = $pages[$pageid]->nextpageid;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_print_tree_link_menu($page, $id, $showpages=false) {
|
|
// prints the actual link for the left menu
|
|
|
|
if ($page->qtype == LESSON_BRANCHTABLE && !$page->display) {
|
|
return false;
|
|
} elseif ($page->qtype != LESSON_BRANCHTABLE) {
|
|
return false;
|
|
}
|
|
|
|
/*elseif ($page->qtype != LESSON_BRANCHTABLE && !$showpages) {
|
|
return false;
|
|
} elseif (!in_array($page->qtype, $LESSON_QUESTION_TYPE)) {
|
|
return false;
|
|
}*/
|
|
|
|
// set up some variables NoticeFix changed whole function
|
|
$output = "";
|
|
$close = false;
|
|
$link="id=$id&action=navigation&pageid=".$page->id;
|
|
|
|
$output = "<li>";
|
|
|
|
if (isset($_REQUEST['pageid'])) {
|
|
if($page->id == $_REQUEST['pageid']) {
|
|
$close=true;
|
|
$output.="<em>";
|
|
}
|
|
}
|
|
|
|
$output .= "<a href=\"view.php?id=$id&action=navigation&pageid=$page->id\">".$page->title."</a>\n";
|
|
|
|
if($close) {
|
|
$output.="</em>";
|
|
}
|
|
$output .= "</li>";
|
|
|
|
|
|
echo $output;
|
|
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_print_tree($pageid, $lessonid, $cmid, $pixpath) {
|
|
// this function prints out the tree view list
|
|
global $USER;
|
|
|
|
if(!$pages = get_records_select("lesson_pages", "lessonid = $lessonid")) {
|
|
error("Error: could not find lesson pages");
|
|
}
|
|
echo "<table>";
|
|
while ($pageid != 0) {
|
|
echo "<tr><td>";
|
|
if(($pages[$pageid]->qtype != LESSON_BRANCHTABLE) && ($pages[$pageid]->qtype != LESSON_ENDOFBRANCH)) {
|
|
$output = "<a style='color:#DF041E;' href=\"view.php?id=$cmid&display=".$pages[$pageid]->id."\">".$pages[$pageid]->title."</a>\n";
|
|
} else {
|
|
$output = "<a href=\"view.php?id=$cmid&display=".$pages[$pageid]->id."\">".$pages[$pageid]->title."</a>\n";
|
|
|
|
if($answers = get_records_select("lesson_answers", "lessonid = $lessonid and pageid = $pageid")) {
|
|
$output .= "Jumps to: ";
|
|
$end = end($answers);
|
|
foreach ($answers as $answer) {
|
|
if ($answer->jumpto == 0) {
|
|
$output .= get_string("thispage", "lesson");
|
|
} elseif ($answer->jumpto == LESSON_NEXTPAGE) {
|
|
$output .= get_string("nextpage", "lesson");
|
|
} elseif ($answer->jumpto == LESSON_EOL) {
|
|
$output .= get_string("endoflesson", "lesson");
|
|
} elseif ($answer->jumpto == LESSON_UNSEENBRANCHPAGE) {
|
|
$output .= get_string("unseenpageinbranch", "lesson");
|
|
} elseif ($answer->jumpto == LESSON_PREVIOUSPAGE) {
|
|
$output .= get_string("previouspage", "lesson");
|
|
} elseif ($answer->jumpto == LESSON_RANDOMPAGE) {
|
|
$output .= get_string("randompageinbranch", "lesson");
|
|
} elseif ($answer->jumpto == LESSON_RANDOMBRANCH) {
|
|
$output .= get_string("randombranch", "lesson");
|
|
} elseif ($answer->jumpto == LESSON_CLUSTERJUMP) {
|
|
$output .= get_string("clusterjump", "lesson");
|
|
} else {
|
|
$output .= $pages[$answer->jumpto]->title;
|
|
}
|
|
if ($answer->id != $end->id) {
|
|
$output .= ", ";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
echo $output;
|
|
if (count($pages) > 1) {
|
|
echo "<a title=\"move\" href=\"lesson.php?id=$cmid&action=move&pageid=".$pages[$pageid]->id."\">\n".
|
|
"<img src=\"$pixpath/t/move.gif\" hspace=\"2\" height=11 width=11 alt=\"move\" border=0></a>\n"; //CDC alt text added.
|
|
}
|
|
echo "<a title=\"update\" href=\"lesson.php?id=$cmid&action=editpage&pageid=".$pages[$pageid]->id."\">\n".
|
|
"<img src=\"$pixpath/t/edit.gif\" hspace=\"2\" height=11 width=11 alt=\"edit\" border=0></a>\n".
|
|
"<a title=\"delete\" href=\"lesson.php?id=$cmid&sesskey=".$USER->sesskey."&action=confirmdelete&pageid=".$pages[$pageid]->id."\">\n".
|
|
"<img src=\"$pixpath/t/delete.gif\" hspace=\"2\" height=11 width=11 alt=\"delete\" border=0></a>\n"; //CDC alt text added.
|
|
|
|
echo "</tr></td>";
|
|
$pageid = $pages[$pageid]->nextpageid;
|
|
}
|
|
echo "</table>";
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_calculate_ongoing_score($lesson, $userid, $retries, $return=false) {
|
|
// this calculates and prints the ongoing score for students
|
|
if (!$lesson->custom) {
|
|
$ncorrect = 0;
|
|
$temp = array();
|
|
if ($pagesanswered = get_records_select("lesson_attempts", "lessonid = $lesson->id AND
|
|
userid = $userid AND retry = $retries order by timeseen")) {
|
|
|
|
foreach ($pagesanswered as $pageanswered) {
|
|
if (!array_key_exists($pageanswered->pageid, $temp)) {
|
|
$temp[$pageanswered->pageid] = array($pageanswered->correct, 1);
|
|
} else {
|
|
if ($temp[$pageanswered->pageid][1] < $lesson->maxattempts) {
|
|
$n = $temp[$pageanswered->pageid][1] + 1;
|
|
$temp[$pageanswered->pageid] = array($pageanswered->correct, $n);
|
|
}
|
|
}
|
|
}
|
|
foreach ($temp as $value => $key) {
|
|
if ($key[0] == 1) {
|
|
$ncorrect += 1;
|
|
}
|
|
}
|
|
}
|
|
$nviewed = count($temp); // this counts number of Questions the user viewed
|
|
$thegrade = intval(100 * $ncorrect / $nviewed);
|
|
|
|
if ($return) {
|
|
return $thegrade;
|
|
} else {
|
|
$output = new stdClass;
|
|
$output->correct = $ncorrect;
|
|
$output->viewed = $nviewed;
|
|
print_simple_box(get_string("ongoingnormal", "lesson", $output), "center");
|
|
}
|
|
|
|
} else {
|
|
$score = 0;
|
|
$essayquestions = 0;
|
|
$essayquestionpoints = 0;
|
|
$bestscore = 0;
|
|
$thegrade = 0;
|
|
|
|
if ($useranswers = get_records_select("lesson_attempts", "lessonid = $lesson->id AND
|
|
userid = $userid AND retry = $retries", "timeseen")) {
|
|
// group each try with its page
|
|
foreach ($useranswers as $useranswer) {
|
|
$attemptset[$useranswer->pageid][] = $useranswer;
|
|
}
|
|
|
|
$pageids = array_keys($attemptset);
|
|
$pageids = implode(",", $pageids);
|
|
|
|
// get only the pages and their answers that the user answered
|
|
$answeredpages = get_records_select("lesson_pages", "lessonid = $lesson->id AND id IN($pageids)");
|
|
$pageanswers = get_records_select("lesson_answers", "lessonid = $lesson->id AND pageid IN($pageids)");
|
|
|
|
foreach ($attemptset as $attempts) {
|
|
if(count($attempts) > $lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt
|
|
$attempt = $attempts[$lesson->maxattempts - 1];
|
|
} else {
|
|
// else, user attempted the question less than the max, so grab the last one
|
|
$attempt = end($attempts);
|
|
}
|
|
// if essay question, handle it, otherwise add to score
|
|
if ($answeredpages[$attempt->pageid]->qtype == LESSON_ESSAY) {
|
|
$essayinfo = unserialize($attempt->useranswer);
|
|
$score += $essayinfo->score;
|
|
$essayquestions++;
|
|
$essayquestionpoints += $pageanswers[$attempt->answerid]->score;
|
|
} else {
|
|
$score += $pageanswers[$attempt->answerid]->score;
|
|
}
|
|
}
|
|
$bestscores = array();
|
|
// find the highest possible score per page
|
|
foreach ($pageanswers as $pageanswer) {
|
|
if(isset($bestscores[$pageanswer->pageid])) {
|
|
if ($bestscores[$pageanswer->pageid] < $pageanswer->score) {
|
|
$bestscores[$pageanswer->pageid] = $pageanswer->score;
|
|
}
|
|
} else {
|
|
$bestscores[$pageanswer->pageid] = $pageanswer->score;
|
|
}
|
|
}
|
|
|
|
$bestscore = array_sum($bestscores);
|
|
$thegrade = intval(100 * $score / $bestscore);
|
|
}
|
|
|
|
|
|
if ($return) {
|
|
return $thegrade;
|
|
} else {
|
|
// not taking into account essay questions... may want to?
|
|
$ongoingoutput = new stdClass;
|
|
$ongoingoutput->score = $score;
|
|
$ongoingoutput->currenthigh = $bestscore;
|
|
print_simple_box(get_string("ongoingcustom", "lesson", $ongoingoutput), "center");
|
|
}
|
|
}
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_qtype_menu($qtypes, $selected="", $link="", $onclick="") {
|
|
// prints the question types for when editing and adding a page
|
|
|
|
$output = "";
|
|
foreach ($qtypes as $value => $label) {
|
|
if ($value == $selected) {
|
|
$output .= "<b>$label</b>";
|
|
$output .= "<input type=\"hidden\" name=\"qtype\" value=\"$value\" /> \n";
|
|
} else {
|
|
$output .= "<a onClick=\"$onclick\" href=\"$link"."&qtype=$value\">$label</a>";
|
|
}
|
|
if ($label != end($qtypes)) {
|
|
$output .= " | ";
|
|
}
|
|
}
|
|
echo $output;
|
|
}
|
|
|
|
/*******************************************************************/
|
|
function lesson_check_nickname($name) {
|
|
// used to check high score nicknames.
|
|
// checks nickname against a list of "bad words"
|
|
|
|
if (empty($name)) {
|
|
return false;
|
|
}
|
|
|
|
$filterwords = explode(',', get_string('censorbadwords'));
|
|
|
|
foreach ($filterwords as $filterword) {
|
|
if (strstr($name, $filterword)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// CDC-FLAG ///
|
|
|
|
?>
|