Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[BugFix] Bug #5405 - made a new function that grades a lesson for a s…

…pecific user's attempt. This is then used for grad

ing lessons at the end of a lesson, for ongoing score feature and for updating the grade for essay question grading.

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.
  • Loading branch information...
commit 2711fbb039783e8a7e36905deb4df518b6dd35ed 1 parent d226ade
mark-nielsen authored
Showing with 171 additions and 235 deletions.
  1. +2 −10 mod/lesson/action/continue.php
  2. +133 −101 mod/lesson/locallib.php
  3. +36 −124 mod/lesson/view.php
View
12 mod/lesson/action/continue.php
@@ -704,17 +704,9 @@
}
}
- // 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!)
View
234 mod/lesson/locallib.php
@@ -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");
}
}
}
View
160 mod/lesson/view.php
@@ -630,45 +630,28 @@
}
}
- /// 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";
}
}
@@ -1019,110 +1002,40 @@
$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
@@ -1821,10 +1734,9 @@
$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 {
Please sign in to comment.
Something went wrong with that request. Please try again.