updated displayleft.html and adding a new help file
[moodle.git] / mod / lesson / locallib.php
CommitLineData
5e7856af 1<?php
2/// mnielsen @ CDC
3/// locallib.php is the new lib file for lesson module.
4/// including locallib.php is the same as including the old lib.php
ac8e16be 5
5e7856af 6if (!defined("LESSON_UNSEENPAGE")) {
ac8e16be 7 define("LESSON_UNSEENPAGE", 1); // Next page -> any page not seen before
8 }
5e7856af 9if (!defined("LESSON_UNANSWEREDPAGE")) {
ac8e16be 10 define("LESSON_UNANSWEREDPAGE", 2); // Next page -> any page not answered correctly
11 }
5e7856af 12
13$LESSON_NEXTPAGE_ACTION = array (0 => get_string("normal", "lesson"),
14 LESSON_UNSEENPAGE => get_string("showanunseenpage", "lesson"),
15 LESSON_UNANSWEREDPAGE => get_string("showanunansweredpage", "lesson") );
16
17
18if (!defined("LESSON_NEXTPAGE")) {
ac8e16be 19 define("LESSON_NEXTPAGE", -1); // Next page
20 }
5e7856af 21if (!defined("LESSON_EOL")) {
ac8e16be 22 define("LESSON_EOL", -9); // End of Lesson
23 }
5e7856af 24/// CDC-FLAG 6/14/04 ///
25if (!defined("LESSON_UNSEENBRANCHPAGE")) {
ac8e16be 26 define("LESSON_UNSEENBRANCHPAGE", -50); // Unseen branch page
27 }
5e7856af 28if (!defined("LESSON_PREVIOUSPAGE")) {
ac8e16be 29 define("LESSON_PREVIOUSPAGE", -40); // previous page
30 }
5e7856af 31if (!defined("LESSON_RANDOMPAGE")) {
ac8e16be 32 define("LESSON_RANDOMPAGE", -60); // random branch page
33 }
5e7856af 34if (!defined("LESSON_RANDOMBRANCH")) {
ac8e16be 35 define("LESSON_RANDOMBRANCH", -70); // random branch
36 }
5e7856af 37if (!defined("LESSON_CLUSTERJUMP")) {
ac8e16be 38 define("LESSON_CLUSTERJUMP", -80); // random within a cluster
39 }
40/// CDC-FLAG ///
5e7856af 41if (!defined("LESSON_UNDEFINED")) {
ac8e16be 42 define("LESSON_UNDEFINED", -99); // undefined
43 }
5e7856af 44
45if (!defined("LESSON_SHORTANSWER")) {
46 define("LESSON_SHORTANSWER", "1");
47}
48if (!defined("LESSON_TRUEFALSE")) {
49 define("LESSON_TRUEFALSE", "2");
50}
b9869082 51if (!defined("LESSON_MULTICHOICE")) { // if you change the value of this (WHICH YOU SHOULDNT) then you need to change it in restorelib.php as well
5e7856af 52 define("LESSON_MULTICHOICE", "3");
53}
54if (!defined("LESSON_RANDOM")) {
55 define("LESSON_RANDOM", "4");
56}
afbc9cbd 57if (!defined("LESSON_MATCHING")) { // if you change the value of this (WHICH YOU SHOULDNT) then you need to change it in restorelib.php, in mysql.php and postgres7.php as well
b9869082 58 define("LESSON_MATCHING", "5");
5e7856af 59}
60if (!defined("LESSON_RANDOMSAMATCH")) {
61 define("LESSON_RANDOMSAMATCH", "6");
62}
63if (!defined("LESSON_DESCRIPTION")) {
64 define("LESSON_DESCRIPTION", "7");
65}
66if (!defined("LESSON_NUMERICAL")) {
67 define("LESSON_NUMERICAL", "8");
68}
69if (!defined("LESSON_MULTIANSWER")) {
70 define("LESSON_MULTIANSWER", "9");
71}
72/// CDC-FLAG /// 6/16/04
73if (!defined("LESSON_ESSAY")) {
ac8e16be 74 define("LESSON_ESSAY", "10");
5e7856af 75}
76if (!defined("LESSON_CLUSTER")) {
77 define("LESSON_CLUSTER", "30");
78}
79if (!defined("LESSON_ENDOFCLUSTER")) {
80 define("LESSON_ENDOFCLUSTER", "31");
81}
82/// CDC-FLAG ///
83
84$LESSON_QUESTION_TYPE = array ( LESSON_MULTICHOICE => get_string("multichoice", "quiz"),
85 LESSON_TRUEFALSE => get_string("truefalse", "quiz"),
86 LESSON_SHORTANSWER => get_string("shortanswer", "quiz"),
87 LESSON_NUMERICAL => get_string("numerical", "quiz"),
88 LESSON_MATCHING => get_string("match", "quiz"),
ac8e16be 89 LESSON_ESSAY => get_string("essay", "lesson") /// CDC-FLAG 6/16/04
5e7856af 90// LESSON_DESCRIPTION => get_string("description", "quiz"),
91// LESSON_RANDOM => get_string("random", "quiz"),
92// LESSON_RANDOMSAMATCH => get_string("randomsamatch", "quiz"),
93// LESSON_MULTIANSWER => get_string("multianswer", "quiz"),
94 );
95
96if (!defined("LESSON_BRANCHTABLE")) {
97 define("LESSON_BRANCHTABLE", "20");
98}
99if (!defined("LESSON_ENDOFBRANCH")) {
100 define("LESSON_ENDOFBRANCH", "21");
101}
102
103if (!defined("LESSON_ANSWER_EDITOR")) {
104 define("LESSON_ANSWER_EDITOR", "1");
105}
106if (!defined("LESSON_RESPONSE_EDITOR")) {
107 define("LESSON_RESPONSE_EDITOR", "2");
108}
109
110//////////////////////////////////////////////////////////////////////////////////////
111/// Any other lesson functions go here. Each of them must have a name that
112/// starts with lesson_
113
114/*******************************************************************/
115function lesson_save_question_options($question) {
116/// Given some question info and some data about the the answers
117/// this function parses, organises and saves the question
118/// This is only used when IMPORTING questions and is only called
119/// from format.php
120/// Lifted from mod/quiz/lib.php -
121/// 1. all reference to oldanswers removed
122/// 2. all reference to quiz_multichoice table removed
123/// 3. In SHORTANSWER questions usecase is store in the qoption field
124/// 4. In NUMERIC questions store the range as two answers
125/// 5. TRUEFALSE options are ignored
126/// 6. For MULTICHOICE questions with more than one answer the qoption field is true
127///
128/// Returns $result->error or $result->notice
129
130 $timenow = time();
131 switch ($question->qtype) {
132 case LESSON_SHORTANSWER:
133
134 $answers = array();
135 $maxfraction = -1;
136
137 // Insert all the new answers
138 foreach ($question->answer as $key => $dataanswer) {
139 if ($dataanswer != "") {
f7ffb898 140 $answer = new stdClass;
5e7856af 141 $answer->lessonid = $question->lessonid;
142 $answer->pageid = $question->id;
143 if ($question->fraction[$key] >=0.5) {
144 $answer->jumpto = LESSON_NEXTPAGE;
145 }
146 $answer->timecreated = $timenow;
147 $answer->grade = $question->fraction[$key] * 100;
148 $answer->answer = $dataanswer;
149 $answer->feedback = $question->feedback[$key];
150 if (!$answer->id = insert_record("lesson_answers", $answer)) {
151 $result->error = "Could not insert shortanswer quiz answer!";
152 return $result;
153 }
154 $answers[] = $answer->id;
155 if ($question->fraction[$key] > $maxfraction) {
156 $maxfraction = $question->fraction[$key];
157 }
158 }
159 }
160
161
162 /// Perform sanity checks on fractional grades
163 if ($maxfraction != 1) {
164 $maxfraction = $maxfraction * 100;
165 $result->notice = get_string("fractionsnomax", "quiz", $maxfraction);
166 return $result;
167 }
168 break;
169
170 case LESSON_NUMERICAL: // Note similarities to SHORTANSWER
171
172 $answers = array();
173 $maxfraction = -1;
174
175
176 // for each answer store the pair of min and max values even if they are the same
177 foreach ($question->answer as $key => $dataanswer) {
178 if ($dataanswer != "") {
f7ffb898 179 $answer = new stdClass;
5e7856af 180 $answer->lessonid = $question->lessonid;
181 $answer->pageid = $question->id;
182 $answer->jumpto = LESSON_NEXTPAGE;
183 $answer->timecreated = $timenow;
184 $answer->grade = $question->fraction[$key] * 100;
dd192b26 185 $min = $question->answer[$key] - $question->tolerance[$key];
186 $max = $question->answer[$key] + $question->tolerance[$key];
187 $answer->answer = $min.":".$max;
188 // $answer->answer = $question->min[$key].":".$question->max[$key]; original line for min/max
5e7856af 189 $answer->response = $question->feedback[$key];
190 if (!$answer->id = insert_record("lesson_answers", $answer)) {
191 $result->error = "Could not insert numerical quiz answer!";
192 return $result;
193 }
194
195 $answers[] = $answer->id;
196 if ($question->fraction[$key] > $maxfraction) {
197 $maxfraction = $question->fraction[$key];
198 }
199 }
200 }
201
202 /// Perform sanity checks on fractional grades
203 if ($maxfraction != 1) {
204 $maxfraction = $maxfraction * 100;
205 $result->notice = get_string("fractionsnomax", "quiz", $maxfraction);
206 return $result;
207 }
208 break;
209
210
211 case LESSON_TRUEFALSE:
212
213 // the truth
214 $answer->lessonid = $question->lessonid;
215 $answer->pageid = $question->id;
216 $answer->timecreated = $timenow;
217 $answer->answer = get_string("true", "quiz");
218 $answer->grade = $question->answer * 100;
219 if ($answer->grade > 50 ) {
220 $answer->jumpto = LESSON_NEXTPAGE;
221 }
222 if (isset($question->feedbacktrue)) {
223 $answer->response = $question->feedbacktrue;
224 }
225 if (!$true->id = insert_record("lesson_answers", $answer)) {
226 $result->error = "Could not insert quiz answer \"true\")!";
227 return $result;
228 }
229
230 // the lie
f7ffb898 231 $answer = new stdClass;
5e7856af 232 $answer->lessonid = $question->lessonid;
233 $answer->pageid = $question->id;
234 $answer->timecreated = $timenow;
235 $answer->answer = get_string("false", "quiz");
236 $answer->grade = (1 - (int)$question->answer) * 100;
237 if ($answer->grade > 50 ) {
238 $answer->jumpto = LESSON_NEXTPAGE;
239 }
240 if (isset($question->feedbackfalse)) {
241 $answer->response = $question->feedbackfalse;
242 }
243 if (!$false->id = insert_record("lesson_answers", $answer)) {
244 $result->error = "Could not insert quiz answer \"false\")!";
245 return $result;
246 }
247
248 break;
249
250
251 case LESSON_MULTICHOICE:
252
253 $totalfraction = 0;
254 $maxfraction = -1;
255
256 $answers = array();
257
258 // Insert all the new answers
259 foreach ($question->answer as $key => $dataanswer) {
260 if ($dataanswer != "") {
f7ffb898 261 $answer = new stdClass;
5e7856af 262 $answer->lessonid = $question->lessonid;
263 $answer->pageid = $question->id;
264 $answer->timecreated = $timenow;
265 $answer->grade = $question->fraction[$key] * 100;
266 /// CDC-FLAG changed some defaults
ac8e16be 267 /* Original Code
268 if ($answer->grade > 50 ) {
5e7856af 269 $answer->jumpto = LESSON_NEXTPAGE;
270 }
ac8e16be 271 Replaced with: */
272 if ($answer->grade > 50 ) {
273 $answer->jumpto = LESSON_NEXTPAGE;
5e7856af 274 $answer->score = 1;
275 }
ac8e16be 276 // end Replace
5e7856af 277 $answer->answer = $dataanswer;
278 $answer->response = $question->feedback[$key];
279 if (!$answer->id = insert_record("lesson_answers", $answer)) {
280 $result->error = "Could not insert multichoice quiz answer! ";
281 return $result;
282 }
283 // for Sanity checks
284 if ($question->fraction[$key] > 0) {
285 $totalfraction += $question->fraction[$key];
286 }
287 if ($question->fraction[$key] > $maxfraction) {
288 $maxfraction = $question->fraction[$key];
289 }
290 }
291 }
292
293 /// Perform sanity checks on fractional grades
294 if ($question->single) {
295 if ($maxfraction != 1) {
296 $maxfraction = $maxfraction * 100;
297 $result->notice = get_string("fractionsnomax", "quiz", $maxfraction);
298 return $result;
299 }
300 } else {
301 $totalfraction = round($totalfraction,2);
302 if ($totalfraction != 1) {
303 $totalfraction = $totalfraction * 100;
304 $result->notice = get_string("fractionsaddwrong", "quiz", $totalfraction);
305 return $result;
306 }
307 }
308 break;
309
310 case LESSON_MATCHING:
311
312 $subquestions = array();
313
314 $i = 0;
315 // Insert all the new question+answer pairs
316 foreach ($question->subquestions as $key => $questiontext) {
317 $answertext = $question->subanswers[$key]; echo $answertext; echo "<br>"; exit;
318 if (!empty($questiontext) and !empty($answertext)) {
f7ffb898 319 $answer = new stdClass;
5e7856af 320 $answer->lessonid = $question->lessonid;
321 $answer->pageid = $question->id;
322 $answer->timecreated = $timenow;
323 $answer->answer = $questiontext;
324 $answer->response = $answertext;
325 if ($i == 0) {
326 // first answer contains the correct answer jump
327 $answer->jumpto = LESSON_NEXTPAGE;
328 }
329 if (!$subquestion->id = insert_record("lesson_answers", $answer)) {
330 $result->error = "Could not insert quiz match subquestion!";
331 return $result;
332 }
333 $subquestions[] = $subquestion->id;
334 $i++;
335 }
336 }
337
338 if (count($subquestions) < 3) {
339 $result->notice = get_string("notenoughsubquestions", "quiz");
340 return $result;
341 }
342
343 break;
344
345
346 case LESSON_RANDOMSAMATCH:
347 $options->question = $question->id;
348 $options->choose = $question->choose;
349 if ($existing = get_record("quiz_randomsamatch", "question", $options->question)) {
350 $options->id = $existing->id;
351 if (!update_record("quiz_randomsamatch", $options)) {
352 $result->error = "Could not update quiz randomsamatch options!";
353 return $result;
354 }
355 } else {
356 if (!insert_record("quiz_randomsamatch", $options)) {
357 $result->error = "Could not insert quiz randomsamatch options!";
358 return $result;
359 }
360 }
361 break;
362
363 case LESSON_MULTIANSWER:
364 if (!$oldmultianswers = get_records("quiz_multianswers", "question", $question->id, "id ASC")) {
365 $oldmultianswers = array();
366 }
367
368 // Insert all the new multi answers
369 foreach ($question->answers as $dataanswer) {
370 if ($oldmultianswer = array_shift($oldmultianswers)) { // Existing answer, so reuse it
371 $multianswer = $oldmultianswer;
372 $multianswer->positionkey = $dataanswer->positionkey;
373 $multianswer->norm = $dataanswer->norm;
374 $multianswer->answertype = $dataanswer->answertype;
375
376 if (! $multianswer->answers = quiz_save_multianswer_alternatives
377 ($question->id, $dataanswer->answertype,
378 $dataanswer->alternatives, $oldmultianswer->answers))
379 {
380 $result->error = "Could not update multianswer alternatives! (id=$multianswer->id)";
381 return $result;
382 }
383 if (!update_record("quiz_multianswers", $multianswer)) {
384 $result->error = "Could not update quiz multianswer! (id=$multianswer->id)";
385 return $result;
386 }
387 } else { // This is a completely new answer
f7ffb898 388 $multianswer = new stdClass;
5e7856af 389 $multianswer->question = $question->id;
390 $multianswer->positionkey = $dataanswer->positionkey;
391 $multianswer->norm = $dataanswer->norm;
392 $multianswer->answertype = $dataanswer->answertype;
393
394 if (! $multianswer->answers = quiz_save_multianswer_alternatives
395 ($question->id, $dataanswer->answertype,
396 $dataanswer->alternatives))
397 {
398 $result->error = "Could not insert multianswer alternatives! (questionid=$question->id)";
399 return $result;
400 }
401 if (!insert_record("quiz_multianswers", $multianswer)) {
402 $result->error = "Could not insert quiz multianswer!";
403 return $result;
404 }
405 }
406 }
407 break;
408
409 case LESSON_RANDOM:
410 break;
411
412 case LESSON_DESCRIPTION:
413 break;
414
415 default:
416 $result->error = "Unsupported question type ($question->qtype)!";
417 return $result;
418 break;
419 }
420 return true;
421}
422/*******************************************************************/
423function lesson_choose_from_menu ($options, $name, $selected="", $nothing="choose", $script="", $nothingvalue="0", $return=false) {
424/// Given an array of value, creates a popup menu to be part of a form
425/// $options["value"]["label"]
426
427 if ($nothing == "choose") {
428 $nothing = get_string("choose")."...";
429 }
430
431 if ($script) {
432 $javascript = "onChange=\"$script\"";
433 } else {
434 $javascript = "";
435 }
436
437 $output = "<label for=$name class=hidden-label>$name</label><SELECT id=$name NAME=$name $javascript>\n"; //CDC hidden label added.
438 if ($nothing) {
439 $output .= " <OPTION VALUE=\"$nothingvalue\"\n";
440 if ($nothingvalue == $selected) {
441 $output .= " SELECTED";
442 }
443 $output .= ">$nothing</OPTION>\n";
444 }
445 if (!empty($options)) {
446 foreach ($options as $value => $label) {
447 $output .= " <OPTION VALUE=\"$value\"";
448 if ($value == $selected) {
449 $output .= " SELECTED";
450 }
ac8e16be 451 // stop zero label being replaced by array index value
5e7856af 452 // if ($label) {
453 // $output .= ">$label</OPTION>\n";
454 // } else {
455 // $output .= ">$value</OPTION>\n";
ac8e16be 456 // }
457 $output .= ">$label</OPTION>\n";
5e7856af 458
459 }
460 }
461 $output .= "</SELECT>\n";
462
463 if ($return) {
464 return $output;
465 } else {
466 echo $output;
467 }
468}
469
470/*******************************************************************/
471function lesson_iscorrect($pageid, $jumpto) {
472 // returns true is jumpto page is (logically) after the pageid page, other returns false
473
474 // first test the special values
475 if (!$jumpto) {
476 // same page
477 return false;
478 } elseif ($jumpto == LESSON_NEXTPAGE) {
479 return true;
ac8e16be 480 /// CDC-FLAG 6/21/04 ///
481 } elseif ($jumpto == LESSON_UNSEENBRANCHPAGE) {
5e7856af 482 return true;
483 } elseif ($jumpto == LESSON_RANDOMPAGE) {
484 return true;
485 } elseif ($jumpto == LESSON_CLUSTERJUMP) {
486 return true;
ac8e16be 487 /// CDC-FLAG ///
5e7856af 488 } elseif ($jumpto == LESSON_EOL) {
489 return true;
490 }
491 // we have to run through the pages from pageid looking for jumpid
492 $apageid = get_field("lesson_pages", "nextpageid", "id", $pageid);
493 while (true) {
494 if ($jumpto == $apageid) {
495 return true;
496 }
497 if ($apageid) {
498 $apageid = get_field("lesson_pages", "nextpageid", "id", $apageid);
499 } else {
500 return false;
501 }
502 }
503 return false; // should never be reached
504}
505
506/// CDC-FLAG ///
507/*******************************************************************/
508function lesson_display_branch_jumps($lesson_id, $pageid) {
509// this fucntion checks to see if a page is a branch or is
510// a page that is enclosed by a branch table and an endofbranch/eol
511
ac8e16be 512 // NoticeFix ... this may cause problems... not sure
513 if($pageid == 0) {
514 // first page
515 return false;
516 }
517 // get all of the lesson pages
518 if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson_id")) {
519 // adding first page
520 return false;
521 }
522
523 if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
524 return true;
525 }
526
527 return lesson_is_page_in_branch($lessonpages, $pageid);
5e7856af 528}
529
530/*******************************************************************/
531function lesson_display_cluster_jump($lesson_id, $pageid) {
532// this fucntion checks to see if a page is a cluster page or is
533// a page that is enclosed by a cluster page and an endofcluster/eol
534
ac8e16be 535 // NoticeFix ... this may cause problems... not sure
536 if($pageid == 0) {
537 // first page
538 return false;
539 }
540 // get all of the lesson pages
541 if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson_id")) {
542 // adding first page
543 return false;
544 }
545
546 if ($lessonpages[$pageid]->qtype == LESSON_CLUSTER) {
547 return true;
548 }
549
550 return lesson_is_page_in_cluster($lessonpages, $pageid);
5e7856af 551
552}
553
554// 6/21/04
555/*******************************************************************/
556function execute_teacherwarning($lesson) {
557// this function checks to see if a LESSON_CLUSTERJUMP or
558// a LESSON_UNSEENBRANCHPAGE is used in a lesson.
559// This function is only executed when a teacher is
560// checking the navigation for a lesson.
561
ac8e16be 562 // get all of the lesson answers
563 if (!$lessonanswers = get_records_select("lesson_answers", "lessonid = $lesson")) {
564 // no answers, then not useing cluster or unseen
565 return false;
566 }
567 // just check for the first one that fulfills the requirements
568 foreach ($lessonanswers as $lessonanswer) {
569 if ($lessonanswer->jumpto == LESSON_CLUSTERJUMP || $lessonanswer->jumpto == LESSON_UNSEENBRANCHPAGE) {
570 return true;
571 }
572 }
573
574 // if no answers use either of the two jumps
575 return false;
5e7856af 576}
577
578
579// 6/18/04
580/*******************************************************************/
581function lesson_cluster_jump($lesson, $user, $pageid) {
582// this fucntion interprets LESSON_CLUSTERJUMP
583// it will select a page randomly
584// and the page selected will be inbetween a cluster page and endofcluter/eol
585// and the page selected will be a page that has not been viewed already
586// and if any pages are within a branchtable/endofbranch then only 1 page within
587// the branchtable/endofbranch will be randomly selected (sub clustering)
588
ac8e16be 589 // get the number of retakes
5e7856af 590 if (!$retakes = count_records("lesson_grades", "lessonid", $lesson, "userid", $user)) {
ac8e16be 591 $retakes = 0;
592 }
593
594 // get all the lesson_attempts aka what the user has seen
595 if ($seen = get_records_select("lesson_attempts", "lessonid = $lesson AND userid = $user AND retry = $retakes", "timeseen DESC")) {
596 foreach ($seen as $value) { // load it into an array that I can more easily use
597 $seenpages[$value->pageid] = $value->pageid;
598 }
599 } else {
600 $seenpages = array();
601 }
602
603 // get the lesson pages
604 if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson")) {
605 error("Error: could not find records in lesson_pages table");
606 }
607 // find the start of the cluster
608 while ($pageid != 0) { // this condition should not be satisfied... should be a cluster page
609 if ($lessonpages[$pageid]->qtype == LESSON_CLUSTER) {
610 break;
611 }
612 $pageid = $lessonpages[$pageid]->prevpageid;
613 }
614
615 $pageid = $lessonpages[$pageid]->nextpageid; // move down from the cluster page
616
617 $clusterpages = array();
618 while (true) { // now load all the pages into the cluster that are not already inside of a branch table.
619 if ($lessonpages[$pageid]->qtype == LESSON_ENDOFCLUSTER) {
620 // store the endofcluster page's jump
621 $exitjump = get_field("lesson_answers", "jumpto", "pageid", $pageid, "lessonid", $lesson);
622 if ($exitjump == LESSON_NEXTPAGE) {
623 $exitjump = $lessonpages[$pageid]->nextpageid;
624 }
625 if ($exitjump == 0) {
626 $exitjump = LESSON_EOL;
627 }
628 break;
629 } elseif (!lesson_is_page_in_branch($lessonpages, $pageid) && $lessonpages[$pageid]->qtype != LESSON_ENDOFBRANCH) {
630 // load page into array when it is not in a branch table and when it is not an endofbranch
631 $clusterpages[] = $lessonpages[$pageid];
632 }
633 if ($lessonpages[$pageid]->nextpageid == 0) {
634 // shouldn't ever get here... should be using endofcluster
635 $exitjump = LESSON_EOL;
636 break;
637 } else {
638 $pageid = $lessonpages[$pageid]->nextpageid;
639 }
640 }
641
642 // filter out the ones we have seen
643 $unseen = array();
644 foreach ($clusterpages as $clusterpage) {
645 if ($clusterpage->qtype == LESSON_BRANCHTABLE) { // if branchtable, check to see if any pages inside have been viewed
646 $branchpages = lesson_pages_in_branch($lessonpages, $clusterpage->id); // get the pages in the branchtable
647 $flag = true;
648 foreach ($branchpages as $branchpage) {
649 if (array_key_exists($branchpage->id, $seenpages)) { // check if any of the pages have been viewed
650 $flag = false;
651 }
652 }
653 if ($flag && count($branchpages) > 0) {
654 // add branch table
655 $unseen[] = $clusterpage;
656 }
657 } else {
658 // add any other type of page that has not already been viewed
659 if (!array_key_exists($clusterpage->id, $seenpages)) {
660 $unseen[] = $clusterpage;
661 }
662 }
663 }
664
665 if (count($unseen) > 0) { // it does not contain elements, then use exitjump, otherwise find out next page/branch
666 $nextpage = $unseen[rand(0, count($unseen)-1)];
667 } else {
668 return $exitjump; // seen all there is to see, leave the cluster
669 }
670
671 if ($nextpage->qtype == LESSON_BRANCHTABLE) { // if branch table, then pick a random page inside of it
672 $branchpages = lesson_pages_in_branch($lessonpages, $nextpage->id);
673 return $branchpages[rand(0, count($branchpages)-1)]->id;
674 } else { // otherwise, return the page's id
675 return $nextpage->id;
676 }
5e7856af 677}
678
679/*******************************************************************/
680function lesson_pages_in_branch($lessonpages, $branchid) {
681// returns pages that are within a branch
ac8e16be 682
683 $pageid = $lessonpages[$branchid]->nextpageid; // move to the first page after the branch table
684 $pagesinbranch = array();
685
686 while (true) {
687 if ($pageid == 0) { // EOL
688 break;
689 } elseif ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
690 break;
691 } elseif ($lessonpages[$pageid]->qtype == LESSON_ENDOFBRANCH) {
692 break;
693 }
694 $pagesinbranch[] = $lessonpages[$pageid];
695 $pageid = $lessonpages[$pageid]->nextpageid;
696 }
697
698 return $pagesinbranch;
5e7856af 699}
700
701/*******************************************************************/
702function lesson_unseen_question_jump($lesson, $user, $pageid) {
703// This function interprets the LESSON_UNSEENBRANCHPAGE jump.
704// will return the pageid of a random unseen page that is within a branch
705
ac8e16be 706 // get the number of retakes
5e7856af 707 if (!$retakes = count_records("lesson_grades", "lessonid", $lesson, "userid", $user)) {
ac8e16be 708 $retakes = 0;
709 }
710
711 // get all the lesson_attempts aka what the user has seen
712 if ($viewedpages = get_records_select("lesson_attempts", "lessonid = $lesson AND userid = $user AND retry = $retakes", "timeseen DESC")) {
713 foreach($viewedpages as $viewed) {
714 $seenpages[] = $viewed->pageid;
715 }
716 } else {
717 $seenpages = array();
718 }
719
720 // get the lesson pages
721 if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson")) {
722 error("Error: could not find records in lesson_pages table");
723 }
724
725 if ($pageid == LESSON_UNSEENBRANCHPAGE) { // this only happens when a student leaves in the middle of an unseen question within a branch series
726 $pageid = $seenpages[0]; // just change the pageid to the last page viewed inside the branch table
727 }
728
729 // go up the pages till branch table
730 while ($pageid != 0) { // this condition should never be satisfied... only happens if there are no branch tables above this page
731 if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
732 break;
733 }
734 $pageid = $lessonpages[$pageid]->prevpageid;
735 }
736
737 $pagesinbranch = lesson_pages_in_branch($lessonpages, $pageid);
738
739 // this foreach loop stores all the pages that are within the branch table but are not in the $seenpages array
740 $unseen = array();
741 foreach($pagesinbranch as $page) {
742 if (!in_array($page->id, $seenpages)) {
743 $unseen[] = $page->id;
744 }
745 }
746
747 if(count($unseen) == 0) {
748 if(isset($pagesinbranch)) {
749 $temp = end($pagesinbranch);
750 $nextpage = $temp->nextpageid; // they have seen all the pages in the branch, so go to EOB/next branch table/EOL
751 } else {
752 // there are no pages inside the branch, so return the next page
753 $nextpage = $lessonpages[$pageid]->nextpageid;
754 }
755 if ($nextpage == 0) {
756 return LESSON_EOL;
757 } else {
758 return $nextpage;
759 }
760 } else {
761 return $unseen[rand(0, count($unseen)-1)]; // returns a random page id for the next page
762 }
5e7856af 763}
764
765// 6/15/04
766/*******************************************************************/
767function lesson_unseen_branch_jump($lesson, $user) {
768// This will return a random unseen branch table
769
770 if (!$retakes = count_records("lesson_grades", "lessonid", $lesson, "userid", $user)) {
ac8e16be 771 $retakes = 0;
772 }
773
774 if (!$seenbranches = get_records_select("lesson_branch", "lessonid = $lesson AND userid = $user AND retry = $retakes",
775 "timeseen DESC")) {
776 error("Error: could not find records in lesson_branch table");
777 }
778
779 // get the lesson pages
780 if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson")) {
781 error("Error: could not find records in lesson_pages table");
782 }
783
784 // this loads all the viewed branch tables into $seen untill it finds the branch table with the flag
785 // which is the branch table that starts the unseenbranch function
786 $seen = array();
787 foreach ($seenbranches as $seenbranch) {
788 if (!$seenbranch->flag) {
789 $seen[$seenbranch->pageid] = $seenbranch->pageid;
790 } else {
791 $start = $seenbranch->pageid;
792 break;
793 }
794 }
795 // this function searches through the lesson pages to find all the branch tables
796 // that follow the flagged branch table
797 $pageid = $lessonpages[$start]->nextpageid; // move down from the flagged branch table
798 while ($pageid != 0) { // grab all of the branch table till eol
799 if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
800 $branchtables[] = $lessonpages[$pageid]->id;
801 }
802 $pageid = $lessonpages[$pageid]->nextpageid;
803 }
804 $unseen = array();
805 foreach ($branchtables as $branchtable) {
806 // load all of the unseen branch tables into unseen
807 if (!array_key_exists($branchtable, $seen)) {
808 $unseen[] = $branchtable;
809 }
810 }
811 if (count($unseen) > 0) {
812 return $unseen[rand(0, count($unseen)-1)]; // returns a random page id for the next page
813 } else {
814 return LESSON_EOL; // has viewed all of the branch tables
815 }
5e7856af 816}
817
818/*******************************************************************/
819function lesson_random_question_jump($lesson, $pageid) {
820// This function will return the pageid of a random page
821// that is within a branch table
822
ac8e16be 823 // get the lesson pages
824 if (!$lessonpages = get_records_select("lesson_pages", "lessonid = $lesson")) {
825 error("Error: could not find records in lesson_pages table");
826 }
827
828 // go up the pages till branch table
829 while ($pageid != 0) { // this condition should never be satisfied... only happens if there are no branch tables above this page
830
831 if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
832 break;
833 }
834 $pageid = $lessonpages[$pageid]->prevpageid;
835 }
836
837 // get the pages within the branch
838 $pagesinbranch = lesson_pages_in_branch($lessonpages, $pageid);
839
840 if(count($pagesinbranch) == 0) {
841 // there are no pages inside the branch, so return the next page
842 return $lessonpages[$pageid]->nextpageid;
843 } else {
844 return $pagesinbranch[rand(0, count($pagesinbranch)-1)]->id; // returns a random page id for the next page
845 }
5e7856af 846}
847
848// 6/15/04
849/*******************************************************************/
850function lesson_is_page_in_branch($pages, $pageid) {
851// This function's purpose is to check if a page is within a branch or not
852
ac8e16be 853 $pageid = $pages[$pageid]->prevpageid; // move up one
854
855 // go up the pages till branch table
856 while (true) {
857 if ($pageid == 0) { // ran into the beginning of the lesson
858 return false;
859 } elseif ($pages[$pageid]->qtype == LESSON_ENDOFBRANCH) { // ran into the end of another branch table
860 return false;
861 } elseif ($pages[$pageid]->qtype == LESSON_CLUSTER) { // do not look beyond a cluster
862 return false;
863 } elseif ($pages[$pageid]->qtype == LESSON_BRANCHTABLE) { // hit a branch table
864 return true;
865 }
866 $pageid = $pages[$pageid]->prevpageid;
867 }
5e7856af 868
869}
870
871/*******************************************************************/
872function lesson_is_page_in_cluster($pages, $pageid) {
873// This function checks to see if a page is within a cluster or not
874
ac8e16be 875 $pageid = $pages[$pageid]->prevpageid; // move up one
876
877 // go up the pages till branch table
878 while (true) {
879 if ($pageid == 0) { // ran into the beginning of the lesson
880 return false;
881 } elseif ($pages[$pageid]->qtype == LESSON_ENDOFCLUSTER) { // ran into the end of another branch table
882 return false;
883 } elseif ($pages[$pageid]->qtype == LESSON_CLUSTER) { // hit a branch table
884 return true;
885 }
886 $pageid = $pages[$pageid]->prevpageid;
887 }
5e7856af 888}
889
890/*******************************************************************/
b9869082 891function lesson_print_tree_menu($lessonid, $pageid, $id, $showpages=false) {
5e7856af 892// prints the contents of the left menu
893
ac8e16be 894 if(!$pages = get_records_select("lesson_pages", "lessonid = $lessonid")) {
895 error("Error: could not find lesson pages");
896 }
d6941aff 897 echo '<ul>';
ac8e16be 898 while ($pageid != 0) {
899 lesson_print_tree_link_menu($pages[$pageid], $id, true);
900 $pageid = $pages[$pageid]->nextpageid;
901 }
d6941aff 902 echo '</ul>';
5e7856af 903}
904
905/*******************************************************************/
b9869082 906function lesson_print_tree_link_menu($page, $id, $showpages=false) {
5e7856af 907// prints the actual link for the left menu
908
ac8e16be 909 if ($page->qtype == LESSON_BRANCHTABLE && !$page->display) {
910 return false;
911 } elseif ($page->qtype != LESSON_BRANCHTABLE) {
912 return false;
913 }
914
915 /*elseif ($page->qtype != LESSON_BRANCHTABLE && !$showpages) {
916 return false;
917 } elseif (!in_array($page->qtype, $LESSON_QUESTION_TYPE)) {
918 return false;
919 }*/
920
921 // set up some variables NoticeFix changed whole function
922 $output = "";
d6941aff 923 $class = ' class="leftmenu_not_selected_link" ';
ac8e16be 924
925 if (isset($_REQUEST['pageid'])) {
926 if($page->id == $_REQUEST['pageid']) {
d6941aff 927 $class = ' class="leftmenu_selected_link" ';
ac8e16be 928 }
929 }
930
d6941aff 931 $output .= '<li>';
ac8e16be 932
d6941aff 933 $output .= "<a $class href=\"view.php?id=$id&amp;action=navigation&amp;pageid=$page->id\">".format_string($page->title,true)."</a>\n";
934
935 $output .= "</li>";
5e7856af 936
d6941aff 937 echo $output;
5e7856af 938}
939
940/*******************************************************************/
941function lesson_print_tree($pageid, $lessonid, $cmid, $pixpath) {
942// this function prints out the tree view list
ac8e16be 943 global $USER;
944
945 if(!$pages = get_records_select("lesson_pages", "lessonid = $lessonid")) {
946 error("Error: could not find lesson pages");
947 }
948 echo "<table>";
949 while ($pageid != 0) {
950 echo "<tr><td>";
951 if(($pages[$pageid]->qtype != LESSON_BRANCHTABLE) && ($pages[$pageid]->qtype != LESSON_ENDOFBRANCH)) {
68dfc4de 952 $output = "<a style='color:#DF041E;' href=\"view.php?id=$cmid&display=".$pages[$pageid]->id."\">".format_string($pages[$pageid]->title,true)."</a>\n";
ac8e16be 953 } else {
68dfc4de 954 $output = "<a href=\"view.php?id=$cmid&display=".$pages[$pageid]->id."\">".format_string($pages[$pageid]->title,true)."</a>\n";
ac8e16be 955
956 if($answers = get_records_select("lesson_answers", "lessonid = $lessonid and pageid = $pageid")) {
957 $output .= "Jumps to: ";
958 $end = end($answers);
959 foreach ($answers as $answer) {
960 if ($answer->jumpto == 0) {
961 $output .= get_string("thispage", "lesson");
962 } elseif ($answer->jumpto == LESSON_NEXTPAGE) {
963 $output .= get_string("nextpage", "lesson");
964 } elseif ($answer->jumpto == LESSON_EOL) {
965 $output .= get_string("endoflesson", "lesson");
966 } elseif ($answer->jumpto == LESSON_UNSEENBRANCHPAGE) {
967 $output .= get_string("unseenpageinbranch", "lesson");
968 } elseif ($answer->jumpto == LESSON_PREVIOUSPAGE) {
969 $output .= get_string("previouspage", "lesson");
970 } elseif ($answer->jumpto == LESSON_RANDOMPAGE) {
971 $output .= get_string("randompageinbranch", "lesson");
972 } elseif ($answer->jumpto == LESSON_RANDOMBRANCH) {
973 $output .= get_string("randombranch", "lesson");
974 } elseif ($answer->jumpto == LESSON_CLUSTERJUMP) {
975 $output .= get_string("clusterjump", "lesson");
976 } else {
68dfc4de 977 $output .= format_string($pages[$answer->jumpto]->title);
ac8e16be 978 }
979 if ($answer->id != $end->id) {
980 $output .= ", ";
981 }
982 }
983 }
984 }
985
986 echo $output;
987 if (count($pages) > 1) {
988 echo "<a title=\"move\" href=\"lesson.php?id=$cmid&action=move&pageid=".$pages[$pageid]->id."\">\n".
989 "<img src=\"$pixpath/t/move.gif\" hspace=\"2\" height=11 width=11 alt=\"move\" border=0></a>\n"; //CDC alt text added.
990 }
991 echo "<a title=\"update\" href=\"lesson.php?id=$cmid&amp;action=editpage&amp;pageid=".$pages[$pageid]->id."\">\n".
992 "<img src=\"$pixpath/t/edit.gif\" hspace=\"2\" height=11 width=11 alt=\"edit\" border=0></a>\n".
993 "<a title=\"delete\" href=\"lesson.php?id=$cmid&amp;sesskey=".$USER->sesskey."&amp;action=confirmdelete&amp;pageid=".$pages[$pageid]->id."\">\n".
994 "<img src=\"$pixpath/t/delete.gif\" hspace=\"2\" height=11 width=11 alt=\"delete\" border=0></a>\n"; //CDC alt text added.
995
996 echo "</tr></td>";
997 $pageid = $pages[$pageid]->nextpageid;
998 }
999 echo "</table>";
5e7856af 1000}
1001
1002/*******************************************************************/
b9869082 1003function lesson_calculate_ongoing_score($lesson, $userid, $retries, $return=false) {
ac8e16be 1004// this calculates and prints the ongoing score for students
1005 if (!$lesson->custom) {
1006 $ncorrect = 0;
1007 $temp = array();
1008 if ($pagesanswered = get_records_select("lesson_attempts", "lessonid = $lesson->id AND
1009 userid = $userid AND retry = $retries order by timeseen")) {
1010
1011 foreach ($pagesanswered as $pageanswered) {
1012 if (!array_key_exists($pageanswered->pageid, $temp)) {
1013 $temp[$pageanswered->pageid] = array($pageanswered->correct, 1);
1014 } else {
1015 if ($temp[$pageanswered->pageid][1] < $lesson->maxattempts) {
1016 $n = $temp[$pageanswered->pageid][1] + 1;
1017 $temp[$pageanswered->pageid] = array($pageanswered->correct, $n);
1018 }
1019 }
1020 }
1021 foreach ($temp as $value => $key) {
1022 if ($key[0] == 1) {
1023 $ncorrect += 1;
1024 }
1025 }
1026 }
1027 $nviewed = count($temp); // this counts number of Questions the user viewed
271fea97 1028 if ($nviewed != 0) {
71ba4dce 1029 $thegrade = round(100 * $ncorrect / $nviewed, 5);
271fea97 1030 } else {
1031 $thegrade = 0;
1032 }
ac8e16be 1033
1034 if ($return) {
1035 return $thegrade;
1036 } else {
1037 $output = new stdClass;
1038 $output->correct = $ncorrect;
1039 $output->viewed = $nviewed;
1040 print_simple_box(get_string("ongoingnormal", "lesson", $output), "center");
1041 }
1042
1043 } else {
1044 $score = 0;
1045 $essayquestions = 0;
1046 $essayquestionpoints = 0;
1047 $bestscore = 0;
1048 $thegrade = 0;
1049
1050 if ($useranswers = get_records_select("lesson_attempts", "lessonid = $lesson->id AND
1051 userid = $userid AND retry = $retries", "timeseen")) {
1052 // group each try with its page
1053 foreach ($useranswers as $useranswer) {
1054 $attemptset[$useranswer->pageid][] = $useranswer;
1055 }
1056
1057 $pageids = array_keys($attemptset);
1058 $pageids = implode(",", $pageids);
1059
1060 // get only the pages and their answers that the user answered
1061 $answeredpages = get_records_select("lesson_pages", "lessonid = $lesson->id AND id IN($pageids)");
1062 $pageanswers = get_records_select("lesson_answers", "lessonid = $lesson->id AND pageid IN($pageids)");
1063
1064 foreach ($attemptset as $attempts) {
1065 if(count($attempts) > $lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt
1066 $attempt = $attempts[$lesson->maxattempts - 1];
1067 } else {
1068 // else, user attempted the question less than the max, so grab the last one
1069 $attempt = end($attempts);
1070 }
1071 // if essay question, handle it, otherwise add to score
1072 if ($answeredpages[$attempt->pageid]->qtype == LESSON_ESSAY) {
1073 $essayinfo = unserialize($attempt->useranswer);
1074 $score += $essayinfo->score;
1075 $essayquestions++;
1076 $essayquestionpoints += $pageanswers[$attempt->answerid]->score;
1077 } else {
1078 $score += $pageanswers[$attempt->answerid]->score;
1079 }
1080 }
1081 $bestscores = array();
1082 // find the highest possible score per page
1083 foreach ($pageanswers as $pageanswer) {
1084 if(isset($bestscores[$pageanswer->pageid])) {
1085 if ($bestscores[$pageanswer->pageid] < $pageanswer->score) {
1086 $bestscores[$pageanswer->pageid] = $pageanswer->score;
1087 }
1088 } else {
1089 $bestscores[$pageanswer->pageid] = $pageanswer->score;
1090 }
1091 }
1092
1093 $bestscore = array_sum($bestscores);
71ba4dce 1094 $thegrade = round(100 * $score / $bestscore, 5);
ac8e16be 1095 }
1096
1097
1098 if ($return) {
1099 return $thegrade;
1100 } else {
1101 // not taking into account essay questions... may want to?
1102 $ongoingoutput = new stdClass;
1103 $ongoingoutput->score = $score;
1104 $ongoingoutput->currenthigh = $bestscore;
1105 print_simple_box(get_string("ongoingcustom", "lesson", $ongoingoutput), "center");
1106 }
1107 }
5e7856af 1108}
1109
1110/*******************************************************************/
1111function lesson_qtype_menu($qtypes, $selected="", $link="", $onclick="") {
1112// prints the question types for when editing and adding a page
271fea97 1113 $tabs = array();
1114 $tabrows = array();
1115
9638a1f4 1116 foreach ($qtypes as $qtype => $qtypename) {
271fea97 1117 $tabrows[] = new tabobject($qtype, "$link&amp;qtype=$qtype\" onClick=\"$onclick\"", $qtypename);
ac8e16be 1118 }
271fea97 1119 $tabs[] = $tabrows;
1120 print_tabs($tabs, $selected);
1121 echo "<input type=\"hidden\" name=\"qtype\" value=\"$selected\" /> \n";
9638a1f4 1122
5e7856af 1123}
1124
1125/*******************************************************************/
1126function lesson_check_nickname($name) {
1127// used to check high score nicknames.
832b9f82 1128// checks nickname against a list of "bad words"
5e7856af 1129
832b9f82 1130 if (empty($name)) {
ac8e16be 1131 return false;
1132 }
1133
832b9f82 1134 $filterwords = explode(',', get_string('censorbadwords'));
ac8e16be 1135
1136 foreach ($filterwords as $filterword) {
1137 if (strstr($name, $filterword)) {
1138 return false;
1139 }
1140 }
1141 return true;
5e7856af 1142}
57bfe93d 1143
5e7856af 1144/// CDC-FLAG ///
1145
2a488ba5 1146?>