]> git.mjollnir.org Git - moodle.git/commitdiff
[Merged][BugFix] Bug #5405 - made a new function that grades a lesson for a specific...
authormark-nielsen <mark-nielsen>
Fri, 19 May 2006 01:05:13 +0000 (01:05 +0000)
committermark-nielsen <mark-nielsen>
Fri, 19 May 2006 01:05:13 +0000 (01:05 +0000)
This new grading algorithm now enforces the lesson setting Max attempts when custom scoring is turned Off

Changed the reporting of minquestions setting to match the help file.  Now it is question based instead of attempt based.

Changed the reporting of ongoing score to use the new grade function.

lang/en_utf8/lesson.php
mod/lesson/action/continue.php
mod/lesson/locallib.php
mod/lesson/view.php

index 334e2ee36ec161c03bfd9892ca71d56a914135f3..48ada606c72eb9873cd40f3e9ef2b4367cb3614c 100644 (file)
@@ -179,10 +179,10 @@ $string['notitle'] = 'No title';
 $string['numberofcorrectanswers'] = 'Number of correct answers: $a';
 $string['numberofcorrectmatches'] = 'Number of correct matches: $a';
 $string['numberofpagestoshow'] = 'Number of pages (cards) to show';
-$string['numberofpagesviewed'] = 'Number of pages viewed: $a';
+$string['numberofpagesviewed'] = 'Number of questions answered: $a';
 $string['ongoing'] = 'Display ongoing score';
 $string['ongoingcustom'] = 'You have earned $a->score point(s) out of $a->currenthigh point(s) thus far.';
-$string['ongoingnormal'] = 'You have answered $a->correct question(s) correctly out of $a->viewed question(s).';
+$string['ongoingnormal'] = 'You have answered $a->correct correctly out of $a->viewed attempts.';
 $string['or'] = 'OR';
 $string['ordered'] = 'Ordered';
 $string['other'] = 'Other';
@@ -284,7 +284,7 @@ $string['youranswer'] = 'Your answer';
 $string['yourcurrentgradeis'] = 'Your current grade is $a';
 $string['yourgradeisnow'] = 'Your grade for the lesson has been changed to $a';
 $string['yourresponse'] = 'Your response';
-$string['youshouldview'] = 'You should view at least: $a';
+$string['youshouldview'] = 'You should answer at least: $a';
 
 
 
index cd7c3a1379b97ed640269c4f1a6c5573098d475e..0083147a02dd34303bfaf95dd4d7fcb2d2f19323 100644 (file)
             }
         }
     
-        // this calculates the ongoing score
+        // This calculates and prints the ongoing score message
         if ($lesson->ongoing) {
-            if (isteacher($course->id)) {
-                echo "<div align=\"center\">".get_string("teacherongoingwarning", "lesson")."</div><br>";
-            } else {
-                $ntries = count_records("lesson_grades", "lessonid", $lesson->id, "userid", $USER->id);
-                if (isset($USER->modattempts[$lesson->id])) {
-                    $ntries--;
-                }
-                lesson_calculate_ongoing_score($lesson, $USER->id, $ntries);
-            }
+            lesson_print_ongoing_score($lesson);
         }
 
         // display response (if there is one - there should be!)
index ae80f145305dc26d2e425c39125e447962771459..d6798da6acc548b6589cce38cb8310da1daf0cae 100644 (file)
@@ -1204,123 +1204,155 @@ function lesson_print_tree($pageid, $lesson, $cmid) {
 /**
  * Calculates a user's grade for a lesson.
  *
- * This is used for the ongoing score feature.  It will calculate the user's
- * score based on how many points they have earned thus far in the lesson out
- * of the maximum that they could have earned.  Example: user answers 4 questions out
- * of 20.  Of the 4, the user earned 5 points out of a possible 12.  So, their current
- * score would be 5 out of 12 and not 5 out of the total for the whole lesson.
- * This function is also used by essay grading.  It is used to recalculate a students grade
- * after a teacher assigns a grade for an essay.
- * 
  * @param object $lesson The lesson that the user is taking.
- * @param int $userid Id of the user.
  * @param int $retries The attempt number.
- * @param boolean $return A flag to return the grade or print it out.
- * @return float May return the grade.
- * @todo Break out the grading section of this code to use for grading lessons (also have grading code in view.php)
+ * @param int $userid Id of the user (optinal, default current user).
+ * @return object { nquestions => number of questions answered
+                    attempts => number of question attempts
+                    total => max points possible
+                    earned => points earned by student
+                    grade => calculated percentage grade
+                    nmanual => number of manually graded questions
+                    manualpoints => point value for manually graded questions }
  */
-function lesson_calculate_ongoing_score($lesson, $userid, $retries, $return=false) {  
-    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
-        if ($nviewed != 0) {
-            $thegrade = round(100 * $ncorrect / $nviewed, 5);
-        } else {
-            $thegrade = 0;
-        }
+function lesson_grade($lesson, $ntries, $userid = 0) {  
+    global $USER;
 
-        if ($return) {
-            return $thegrade;
-        } else {
-            $output = new stdClass;
-            $output->correct = $ncorrect;
-            $output->viewed = $nviewed;
-            print_simple_box(get_string("ongoingnormal", "lesson", $output), "center");
+    if (empty($userid)) {
+        $userid = $USER->id;
+    }
+    
+    // Zero out everything
+    $ncorrect     = 0;
+    $nviewed      = 0;
+    $score        = 0;
+    $nmanual      = 0;
+    $manualpoints = 0;
+    $thegrade     = 0;
+    $nquestions   = 0;
+    $total        = 0;
+    $earned       = 0;
+
+    if ($useranswers = get_records_select("lesson_attempts",  "lessonid = $lesson->id AND 
+            userid = $userid AND retry = $ntries", "timeseen")) {
+        // group each try with its page
+        $attemptset = array();
+        foreach ($useranswers as $useranswer) {
+            $attemptset[$useranswer->pageid][] = $useranswer;                                
         }
-
-    } 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) {
+        
+        // Drop all attempts that go beyond max attempts for the lesson
+        foreach ($attemptset as $key => $set) {
+            $attemptset[$key] = array_slice($set, 0, $lesson->maxattempts);
+        }
+        
+        $pageids = implode(",", array_keys($attemptset));
+        
+        // get only the pages and their answers that the user answered
+        $pages = get_records_select("lesson_pages", "lessonid = $lesson->id AND id IN($pageids)");
+        $answers = get_records_select("lesson_answers", "lessonid = $lesson->id AND pageid IN($pageids)");
+        
+        // Number of pages answered
+        $nquestions = count($pages);
+
+        foreach ($attemptset as $attempts) {
+            if ($lesson->custom) {
+                $attempt = end($attempts);
+                // If essay question, handle it, otherwise add to score
+                if ($pages[$attempt->pageid]->qtype == LESSON_ESSAY) {
                     $essayinfo = unserialize($attempt->useranswer);
-                    $score += $essayinfo->score;
-                    $essayquestions++;
-                    $essayquestionpoints += $pageanswers[$attempt->answerid]->score;
+                    $earned += $essayinfo->score;
+                    $nmanual++;
+                    $manualpoints += $answers[$attempt->answerid]->score;
                 } else {
-                    $score += $pageanswers[$attempt->answerid]->score;
+                    $earned += $answers[$attempt->answerid]->score;
+                }
+            } else {
+                foreach ($attempts as $attempt) {
+                    $earned += $attempt->correct;
+                }
+                $attempt = end($attempts); // doesn't matter which one
+                // If essay question, increase numbers
+                if ($pages[$attempt->pageid]->qtype == LESSON_ESSAY) {
+                    $nmanual++;
+                    $manualpoints++;
                 }
             }
+            // Number of times answered
+            $nviewed += count($attempts);
+        }
+        
+        if ($lesson->custom) {
             $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;
-                    }
+            // Find the highest possible score per page to get our total
+            foreach ($answers as $answer) {
+                if(isset($bestscores[$answer->pageid]) and $bestscores[$answer->pageid] < $answer->score) {
+                    $bestscores[$answer->pageid] = $answer->score;
                 } else {
-                    $bestscores[$pageanswer->pageid] = $pageanswer->score;
+                    $bestscores[$answer->pageid] = $answer->score;
                 }
             }
-            
-            $bestscore = array_sum($bestscores);
-            $thegrade = round(100 * $score / $bestscore, 5);
+            $total = array_sum($bestscores);
+        } else {
+            // Check to make sure the student has answered the minimum questions
+            if ($lesson->minquestions and $nquestions < $lesson->minquestions) {
+                // Nope, increase number viewed by the amount of unanswered questions
+                $total =  $nviewed + ($lesson->minquestions - $nquestions);
+            } else {
+                $total = $nviewed;
+            }
         }
-            
+    }
+    
+    if ($total) { // not zero
+        $thegrade = round(100 * $earned / $total, 5);
+    }
+    
+    // Build the grade information object
+    $gradeinfo               = new stdClass;
+    $gradeinfo->nquestions   = $nquestions;
+    $gradeinfo->attempts     = $nviewed;
+    $gradeinfo->total        = $total;
+    $gradeinfo->earned       = $earned;
+    $gradeinfo->grade        = $thegrade;
+    $gradeinfo->nmanual      = $nmanual;
+    $gradeinfo->manualpoints = $manualpoints;
+    
+    return $gradeinfo;
+}
+
+/**
+ * Prints the on going message to the user.
+ *
+ * With custom grading On, displays points 
+ * earned out of total points possible thus far.
+ * With custom grading Off, displays number of correct
+ * answers out of total attempted.
+ *
+ * @param object $lesson The lesson that the user is taking.
+ * @return void
+ **/
+function lesson_print_ongoing_score($lesson) {
+    global $USER;
+    
+    if (isteacher($lesson->course)) {
+        echo "<p align=\"center\">".get_string('teacherongoingwarning', 'lesson').'</p>';
+    } else {
+        $ntries = count_records("lesson_grades", "lessonid", $lesson->id, "userid", $USER->id);
+        if (isset($USER->modattempts[$lesson->id])) {
+            $ntries--;
+        }
+        $gradeinfo = lesson_grade($lesson, $ntries);
         
-        if ($return) {
-            return $thegrade;
+        $a = new stdClass;
+        if ($lesson->custom) {
+            $a->score = $gradeinfo->earned;
+            $a->currenthigh = $gradeinfo->total;
+            print_simple_box(get_string("ongoingcustom", "lesson", $a), "center");
         } 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");
+            $a->correct = $gradeinfo->earned;
+            $a->viewed = $gradeinfo->attempts;
+            print_simple_box(get_string("ongoingnormal", "lesson", $a), "center");
         }
     }
 }
index df244a495cb4eaf6e0a33e5d4290ece5f66405fc..01d17d135976717e93a3285a22d792a82137cbf5 100644 (file)
                 }
             }
             
-            /// this calculates the ongoing score
-            if ($lesson->ongoing && !empty($pageid)) {
-                if (isteacher($course->id)) {
-                    echo "<p align=\"center\">".get_string('teacherongoingwarning', 'lesson').'</p>';
-                } else {
-                    $ntries = count_records("lesson_grades", "lessonid", $lesson->id, "userid", $USER->id);
-                    if (isset($USER->modattempts[$lesson->id])) {
-                        $ntries--;
-                    }
-                    lesson_calculate_ongoing_score($lesson, $USER->id, $ntries);                
-                }
+            /// This calculates and prints the ongoing score
+            if ($lesson->ongoing and !empty($pageid)) {
+                lesson_print_ongoing_score($lesson);
             }
             
             if ($page->qtype == LESSON_BRANCHTABLE) {
                 if ($lesson->minquestions and isstudent($course->id)) {
                     // tell student how many questions they have seen, how many are required and their grade
                     $ntries = count_records("lesson_grades", "lessonid", $lesson->id, "userid", $USER->id);
-                    $nviewed = count_records("lesson_attempts", "lessonid", $lesson->id, "userid", 
-                            $USER->id, "retry", $ntries);
-                    if ($nviewed) {
-                        echo "<p align=\"center\">".get_string("numberofpagesviewed", "lesson", $nviewed).
+                    
+                    $gradeinfo = lesson_grade($lesson, $ntries);
+                    
+                    if ($gradeinfo->attempts) {
+                        echo "<p align=\"center\">".get_string("numberofpagesviewed", "lesson", $gradeinfo->nquestions).
                                 "; (".get_string("youshouldview", "lesson", $lesson->minquestions).")<br />";
                         // count the number of distinct correct pages
-                        if ($correctpages = get_records_select("lesson_attempts",  "lessonid = $lesson->id
-                                AND userid = $USER->id AND retry = $ntries AND correct = 1")) {
-                            foreach ($correctpages as $correctpage) {
-                                $temp[$correctpage->pageid] = 1;
-                            }
-                            $ncorrect = count($temp);
-                        } else {
-                            $nccorrect = 0;
+                        if ($gradeinfo->nquestions < $lesson->minquestions) {
+                            $gradeinfo->nquestions = $lesson->minquestions;
                         }
-                        if ($nviewed < $lesson->minquestions) {
-                            $nviewed = $lesson->minquestions;
-                        }
-                        echo get_string("numberofcorrectanswers", "lesson", $ncorrect)."<br />\n";
-                        $thegrade = intval(100 * $ncorrect / $nviewed);
+                        echo get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned)."<br />\n";
                         echo get_string("yourcurrentgradeis", "lesson", 
-                                number_format($thegrade * $lesson->grade / 100, 1)).
+                                number_format($gradeinfo->grade * $lesson->grade / 100, 1)).
                             " (".get_string("outof", "lesson", $lesson->grade).")</p>\n";
                     }
                 }
                 $ntries--;  // need to look at the old attempts :)
             }
             if (isstudent($course->id)) {
-                if ($nviewed = count_records("lesson_attempts", "lessonid", $lesson->id, "userid", 
-                        $USER->id, "retry", $ntries)) {
+                
+                $gradeinfo = lesson_grade($lesson, $ntries);
+                
+                if ($gradeinfo->attempts) {
                     if (!$lesson->custom) {
-                        $ncorrect = 0;                        
-                        $temp = array();
-                        // count the number of distinct correct pages
-                        if ($correctpages = get_records_select("lesson_attempts",  "lessonid = $lesson->id AND
-                                userid = $USER->id AND retry = $ntries AND correct = 1")) {
-                            foreach ($correctpages as $correctpage) {
-                                $temp[$correctpage->pageid] = 1;
-                            }
-                            $ncorrect = count($temp);
-                        }
-                        echo "<p align=\"center\">".get_string("numberofpagesviewed", "lesson", $nviewed).
+                        echo "<p align=\"center\">".get_string("numberofpagesviewed", "lesson", $gradeinfo->nquestions).
                             "</p>\n";
                         if ($lesson->minquestions) {
-                            if ($nviewed < $lesson->minquestions) {
+                            if ($gradeinfo->nquestions < $lesson->minquestions) {
                                 // print a warning and set nviewed to minquestions
                                 echo "<p align=\"center\">".get_string("youshouldview", "lesson", 
-                                        $lesson->minquestions)." ".get_string("pages", "lesson")."</p>\n";
-                                $nviewed = $lesson->minquestions;
+                                        $lesson->minquestions)."</p>\n";
                             }
                         }
-                        echo "<p align=\"center\">".get_string("numberofcorrectanswers", "lesson", $ncorrect).
+                        echo "<p align=\"center\">".get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned).
                             "</p>\n";
-                        $thegrade = round(100 * $ncorrect / $nviewed, 5);
-                        echo "<p align=\"center\">".get_string("gradeis", "lesson", 
-                                number_format($thegrade * $lesson->grade / 100, 1)).
-                            " (".get_string("outof", "lesson", $lesson->grade).")</p>\n";
-                        
+                    }
+                    $a = new stdClass;
+                    $a->score = $gradeinfo->earned;
+                    $a->grade = $gradeinfo->total;
+                    if ($gradeinfo->nmanual) {
+                        $a->tempmaxgrade = $gradeinfo->total - $gradeinfo->manualpoints;
+                        $a->essayquestions = $gradeinfo->nmanual;
+                        echo "<div align=\"center\">".get_string("displayscorewithessays", "lesson", $a)."</div>";
                     } else {
-                        $score = 0;
-                        $essayquestions = 0;
-                        $essayquestionpoints = 0;
-
-                        if ($useranswers = get_records_select("lesson_attempts",  "lessonid = $lesson->id AND 
-                                userid = $USER->id AND retry = $ntries", "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 {
-                                    if (array_key_exists($attempt->answerid, $pageanswers)) {
-                                        $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 = round(100 * $score / $bestscore, 5);
-                        $a = new stdClass;
-                        if ($essayquestions > 0) {
-                            $a->score = $score;
-                            $a->tempmaxgrade = $bestscore - $essayquestionpoints;
-                            $a->essayquestions = $essayquestions;
-                            $a->grade = $bestscore;
-                            echo "<div align=\"center\">".get_string("displayscorewithessays", "lesson", $a)."</div>";
-                        } else {
-                            $a->score = $score;
-                            $a->grade = $bestscore;
-                            echo "<div align=\"center\">".get_string("displayscorewithoutessays", "lesson", $a)."</div>";                        
-                        }
-                        echo "<p align=\"center\">".get_string("gradeis", "lesson", 
-                                number_format($thegrade * $lesson->grade / 100, 1)).
-                            " (".get_string("outof", "lesson", $lesson->grade).")</p>\n";
-
+                        echo "<div align=\"center\">".get_string("displayscorewithoutessays", "lesson", $a)."</div>";                        
                     }
+                    echo "<p align=\"center\">".get_string("gradeis", "lesson", 
+                            number_format($gradeinfo->grade * $lesson->grade / 100, 1)).
+                        " (".get_string("outof", "lesson", $lesson->grade).")</p>\n";
+                        
                     $grade->lessonid = $lesson->id;
                     $grade->userid = $USER->id;
-                    $grade->grade = $thegrade;
+                    $grade->grade = $gradeinfo->grade;
                     $grade->completed = time();
                     if (!$lesson->practice) {
                         if (isset($USER->modattempts[$lesson->id])) { // if reviewing, make sure update old grade record
 
         $grade = current($grades);
 
-        // I modded this function a bit so it would work here...  :) ;) :P
-        $updategrade->grade = lesson_calculate_ongoing_score($lesson, $essay->userid, $essay->retry, true);    
+        $gradeinfo = lesson_grade($lesson, $essay->retry, $essay->userid);    
         $updategrade->id = $grade->id;
-        
+        $updategrade->grade = $gradeinfo->grade;
         if(update_record("lesson_grades", $updategrade)) {
             redirect("view.php?id=$cm->id&amp;action=essayview", get_string("updatesuccess", "lesson"));
         } else {