1
0
mirror of https://github.com/moodle/moodle.git synced 2025-04-17 22:45:54 +02:00

MDL-50516 mod_lesson: fixed issue with grade not using minquestions

It's possible to reach the end of the lesson, get your result,
click back until you get to the last question, answer it correctly
and then be awarded a result of 100%. This was because the grade
calculation would only include the questions answered, rather than
all of them in the lesson. However, you can not fix this by always
grading by the amount of questions in the lesson as some lessons
bypass certain questions depending on the answer to previous ones.
The minquestion setting can now successfully be used to prevent this
behaviour by rewording the misleading string and adding logic.
This commit is contained in:
Mark Nelson 2015-09-03 17:48:11 -07:00 committed by Andrew Nicols
parent d60350ddac
commit 139645d4a7
2 changed files with 120 additions and 101 deletions
mod/lesson

@ -283,9 +283,7 @@ $string['mediaheight'] = 'Popup window height';
$string['mediawidth'] = 'Popup window width';
$string['messageprovider:graded_essay'] = 'Lesson essay graded notification';
$string['minimumnumberofquestions'] = 'Minimum number of questions';
$string['minimumnumberofquestions_help'] = 'This setting specifies the minimum number of questions that will be used to calculate a grade for the activity. If the lesson contains one or more content pages, the minimum number of questions should be set to zero.
If set to say 20, it is suggested that the following text is added to the opening page of the lesson: "In this lesson you are expected to attempt at least 20 questions. You can attempt more if you wish. However, if you attempt less than 20 questions, your grade will be calculated as though you attempted 20."';
$string['minimumnumberofquestions_help'] = 'This setting specifies the minimum number of questions that will be used to calculate a grade for the activity.';
$string['missingname'] = 'Please enter a nickname';
$string['modattempts'] = 'Allow student review';
$string['modattempts_help'] = 'If enabled, students can navigate through the lesson again from the start.';
@ -351,7 +349,7 @@ $string['numberofpagestoshow'] = 'Number of pages to show';
$string['numberofpagestoshow_help'] = 'This setting specifies the number of pages shown in a lesson. It is only applicable for lessons with pages shown in a random order (when "Action after correct answer" is set to "Show an unseen page" or "Show an unanswered page"). If set to zero, then all pages are shown.';
$string['numberofpagesviewed'] = 'Number of questions answered: {$a}';
$string['numberofpagesviewedheader'] = 'Number of questions answered';
$string['numberofpagesviewednotice'] = 'Number of questions answered: {$a->nquestions}; (You should answer at least: {$a->minquestions})';
$string['numberofpagesviewednotice'] = 'Number of questions answered: {$a->nquestions} (You should answer at least {$a->minquestions})';
$string['numerical'] = 'Numerical';
$string['ongoing'] = 'Display ongoing score';
$string['ongoing_help'] = 'If enabled, each page will display the student\'s current points earned out of the total possible thus far.';

@ -442,111 +442,132 @@ if ($pageid != LESSON_EOL) {
// Used to check to see if the student ran out of time
$outoftime = optional_param('outoftime', '', PARAM_ALPHA);
// We are using level 3 header because the page title is a sub-heading of lesson title (MDL-30911).
$lessoncontent .= $OUTPUT->heading(get_string("congratulations", "lesson"), 3);
$lessoncontent .= $OUTPUT->box_start('generalbox boxaligncenter');
$ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id));
if (isset($USER->modattempts[$lesson->id])) {
$ntries--; // need to look at the old attempts :)
}
if (!$canmanage) {
// Store this now before any modifications to pages viewed.
$progressbar = $lessonoutput->progress_bar($lesson);
// Update the clock / get time information for this user.
$lesson->stop_timer();
$gradeinfo = lesson_grade($lesson, $ntries);
// Update completion state.
$completion = new completion_info($course);
if ($completion->is_enabled($cm) && $lesson->completionendreached) {
$completion->update_state($cm, COMPLETION_COMPLETE);
}
if ($lesson->completiontimespent > 0) {
$duration = $DB->get_field_sql(
"SELECT SUM(lessontime - starttime)
FROM {lesson_timer}
WHERE lessonid = :lessonid
AND userid = :userid",
array('userid' => $USER->id, 'lessonid' => $lesson->id));
if (!$duration) {
$duration = 0;
}
// If student has not spend enough time in the lesson, display a message.
if ($duration < $lesson->completiontimespent) {
$a = new stdClass;
$a->timespent = format_time($duration);
$a->timerequired = format_time($lesson->completiontimespent);
$lessoncontent .= $lessonoutput->paragraph(get_string("notenoughtimespent", "lesson", $a), 'center');
}
}
if ($gradeinfo->attempts) {
if (!$lesson->custom) {
$lessoncontent .= $lessonoutput->paragraph(get_string("numberofpagesviewed", "lesson", $gradeinfo->nquestions), 'center');
if ($lesson->minquestions) {
if ($gradeinfo->nquestions < $lesson->minquestions) {
// print a warning and set nviewed to minquestions
$lessoncontent .= $lessonoutput->paragraph(get_string("youshouldview", "lesson", $lesson->minquestions), 'center');
}
}
$lessoncontent .= $lessonoutput->paragraph(get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned), 'center');
}
$gradelesson = true;
$gradeinfo = lesson_grade($lesson, $ntries);
if ($lesson->custom && !$canmanage) {
// Before we calculate the custom score make sure they answered the minimum
// number of questions. We only need to do this for custom scoring as we can
// not get the miniumum score the user should achieve. If we are not using
// custom scoring (so all questions are valued as 1) then we simply check if
// they answered more than the minimum questions, if not, we mark it out of the
// number specified in the minimum questions setting - which is done in lesson_grade().
// Get the number of answers given.
if ($gradeinfo->nquestions < $lesson->minquestions) {
$gradelesson = false;
$a = new stdClass;
$a->score = $gradeinfo->earned;
$a->grade = $gradeinfo->total;
if ($gradeinfo->nmanual) {
$a->tempmaxgrade = $gradeinfo->total - $gradeinfo->manualpoints;
$a->essayquestions = $gradeinfo->nmanual;
$lessoncontent .= $OUTPUT->box(get_string("displayscorewithessays", "lesson", $a), 'center');
} else {
$lessoncontent .= $OUTPUT->box(get_string("displayscorewithoutessays", "lesson", $a), 'center');
}
if ($lesson->grade != GRADE_TYPE_NONE) {
$a = new stdClass;
$a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1);
$a->total = $lesson->grade;
$lessoncontent .= $lessonoutput->paragraph(get_string("yourcurrentgradeisoutof", "lesson", $a), 'center');
}
$grade = new stdClass();
$grade->lessonid = $lesson->id;
$grade->userid = $USER->id;
$grade->grade = $gradeinfo->grade;
$grade->completed = time();
if (isset($USER->modattempts[$lesson->id])) { // If reviewing, make sure update old grade record.
if (!$grades = $DB->get_records("lesson_grades",
array("lessonid" => $lesson->id, "userid" => $USER->id), "completed DESC", '*', 0, 1)) {
print_error('cannotfindgrade', 'lesson');
}
$oldgrade = array_shift($grades);
$grade->id = $oldgrade->id;
$DB->update_record("lesson_grades", $grade);
} else {
$newgradeid = $DB->insert_record("lesson_grades", $grade);
}
} else {
if ($lesson->timelimit) {
if ($outoftime == 'normal') {
$grade = new stdClass();
$grade->lessonid = $lesson->id;
$grade->userid = $USER->id;
$grade->grade = 0;
$grade->completed = time();
$newgradeid = $DB->insert_record("lesson_grades", $grade);
$lessoncontent .= $lessonoutput->paragraph(get_string("eolstudentoutoftimenoanswers", "lesson"));
}
} else {
$lessoncontent .= $lessonoutput->paragraph(get_string("welldone", "lesson"));
}
$a->nquestions = $gradeinfo->nquestions;
$a->minquestions = $lesson->minquestions;
$lessoncontent .= $OUTPUT->box_start('generalbox boxaligncenter');
$lesson->add_message(get_string('numberofpagesviewednotice', 'lesson', $a));
}
}
if ($gradelesson) {
// We are using level 3 header because the page title is a sub-heading of lesson title (MDL-30911).
$lessoncontent .= $OUTPUT->heading(get_string("congratulations", "lesson"), 3);
$lessoncontent .= $OUTPUT->box_start('generalbox boxaligncenter');
}
if (!$canmanage) {
if ($gradelesson) {
// Store this now before any modifications to pages viewed.
$progressbar = $lessonoutput->progress_bar($lesson);
// Update the clock / get time information for this user.
$lesson->stop_timer();
// update central gradebook
lesson_update_grades($lesson, $USER->id);
$lessoncontent .= $progressbar;
// Update completion state.
$completion = new completion_info($course);
if ($completion->is_enabled($cm) && $lesson->completionendreached) {
$completion->update_state($cm, COMPLETION_COMPLETE);
}
if ($lesson->completiontimespent > 0) {
$duration = $DB->get_field_sql(
"SELECT SUM(lessontime - starttime)
FROM {lesson_timer}
WHERE lessonid = :lessonid
AND userid = :userid",
array('userid' => $USER->id, 'lessonid' => $lesson->id));
if (!$duration) {
$duration = 0;
}
// If student has not spend enough time in the lesson, display a message.
if ($duration < $lesson->completiontimespent) {
$a = new stdClass;
$a->timespent = format_time($duration);
$a->timerequired = format_time($lesson->completiontimespent);
$lessoncontent .= $lessonoutput->paragraph(get_string("notenoughtimespent", "lesson", $a), 'center');
}
}
if ($gradeinfo->attempts) {
if (!$lesson->custom) {
$lessoncontent .= $lessonoutput->paragraph(get_string("numberofpagesviewed", "lesson", $gradeinfo->nquestions), 'center');
if ($lesson->minquestions) {
if ($gradeinfo->nquestions < $lesson->minquestions) {
// print a warning and set nviewed to minquestions
$lessoncontent .= $lessonoutput->paragraph(get_string("youshouldview", "lesson", $lesson->minquestions), 'center');
}
}
$lessoncontent .= $lessonoutput->paragraph(get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned), 'center');
}
$a = new stdClass;
$a->score = $gradeinfo->earned;
$a->grade = $gradeinfo->total;
if ($gradeinfo->nmanual) {
$a->tempmaxgrade = $gradeinfo->total - $gradeinfo->manualpoints;
$a->essayquestions = $gradeinfo->nmanual;
$lessoncontent .= $OUTPUT->box(get_string("displayscorewithessays", "lesson", $a), 'center');
} else {
$lessoncontent .= $OUTPUT->box(get_string("displayscorewithoutessays", "lesson", $a), 'center');
}
if ($lesson->grade != GRADE_TYPE_NONE) {
$a = new stdClass;
$a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1);
$a->total = $lesson->grade;
$lessoncontent .= $lessonoutput->paragraph(get_string("yourcurrentgradeisoutof", "lesson", $a), 'center');
}
$grade = new stdClass();
$grade->lessonid = $lesson->id;
$grade->userid = $USER->id;
$grade->grade = $gradeinfo->grade;
$grade->completed = time();
if (isset($USER->modattempts[$lesson->id])) { // If reviewing, make sure update old grade record.
if (!$grades = $DB->get_records("lesson_grades",
array("lessonid" => $lesson->id, "userid" => $USER->id), "completed DESC", '*', 0, 1)) {
print_error('cannotfindgrade', 'lesson');
}
$oldgrade = array_shift($grades);
$grade->id = $oldgrade->id;
$DB->update_record("lesson_grades", $grade);
} else {
$newgradeid = $DB->insert_record("lesson_grades", $grade);
}
} else {
if ($lesson->timelimit) {
if ($outoftime == 'normal') {
$grade = new stdClass();
$grade->lessonid = $lesson->id;
$grade->userid = $USER->id;
$grade->grade = 0;
$grade->completed = time();
$newgradeid = $DB->insert_record("lesson_grades", $grade);
$lessoncontent .= $lessonoutput->paragraph(get_string("eolstudentoutoftimenoanswers", "lesson"));
}
} else {
$lessoncontent .= $lessonoutput->paragraph(get_string("welldone", "lesson"));
}
}
// update central gradebook
lesson_update_grades($lesson, $USER->id);
$lessoncontent .= $progressbar;
}
} else {
// display for teacher
if ($lesson->grade != GRADE_TYPE_NONE) {