From: gustav_delius Date: Fri, 7 Apr 2006 16:00:29 +0000 (+0000) Subject: Manual grading X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=b6e907a245ddbe17a69125725717625e3ede3b72;p=moodle.git Manual grading --- diff --git a/lang/en_utf8/quiz.php b/lang/en_utf8/quiz.php index 9f31bb092a..d4e2f3f49e 100644 --- a/lang/en_utf8/quiz.php +++ b/lang/en_utf8/quiz.php @@ -82,6 +82,8 @@ $string['choosefile'] = 'Choose a file'; $string['close'] = 'Close window'; $string['closepreview'] = 'Close preview'; $string['closereview'] = 'Close review'; +$string['comment'] = 'Comment'; +$string['commentorgrade'] = 'Make comment or override grade'; $string['completedon'] = 'Completed on'; $string['confirmclose'] = 'You are about to close this attempt. Once you close the attempt you will no longer be able to change your answers.'; $string['confirmserverdelete'] = 'Are you sure you want to remove the server $a from the list?'; @@ -159,9 +161,10 @@ $string['event1'] = 'Autosave'; $string['event2'] = 'Save'; $string['event3'] = 'Grade'; $string['event5'] = 'Validate'; -$string['event6'] = 'Close'; +$string['event6'] = 'Close&Grade'; $string['event7'] = 'Submit'; $string['event8'] = 'Close'; +$string['event9'] = 'Manual Grade'; $string['examview'] = 'Examview'; $string['existingcategory1'] = 'a literal from an already existing set of literals that are also used by other questions in this category'; $string['existingcategory2'] = 'a file from an already existing set of files that are also used by other questions in this category'; diff --git a/lib/questionlib.php b/lib/questionlib.php index 1c8ee86728..c8d27c5bde 100644 --- a/lib/questionlib.php +++ b/lib/questionlib.php @@ -685,8 +685,7 @@ function save_question_session(&$question, &$state) { $state->answer = isset($state->responses['']) ? $state->responses[''] : ''; // Save the state - if (isset($state->update)) { // this ->update field is only used by the - // regrading function to force the old state record to be overwritten + if (isset($state->update)) { // this forces the old state record to be overwritten update_record('question_states', $state); } else { if (!$state->id = insert_record('question_states', $state)) { @@ -694,30 +693,30 @@ function save_question_session(&$question, &$state) { unset($state->answer); return false; } + } - // this is the most recent state - if (!record_exists('question_sessions', 'attemptid', - $state->attempt, 'questionid', $question->id)) { - $new->attemptid = $state->attempt; - $new->questionid = $question->id; - $new->newest = $state->id; - $new->sumpenalty = $state->sumpenalty; - if (!insert_record('question_sessions', $new)) { - error('Could not insert entry in question_sessions'); - } - } else { - set_field('question_sessions', 'newest', $state->id, 'attemptid', - $state->attempt, 'questionid', $question->id); + // create or update the session + if (!record_exists('question_sessions', 'attemptid', + $state->attempt, 'questionid', $question->id)) { + $new->attemptid = $state->attempt; + $new->questionid = $question->id; + $new->newest = $state->id; + $new->sumpenalty = $state->sumpenalty; + if (!insert_record('question_sessions', $new)) { + error('Could not insert entry in question_sessions'); } - if (question_state_is_graded($state)) { - // this is also the most recent graded state - if ($newest = get_record('question_sessions', 'attemptid', - $state->attempt, 'questionid', $question->id)) { - $newest->newgraded = $state->id; - $newest->sumpenalty = $state->sumpenalty; - $newest->comment = $state->comment; - update_record('question_sessions', $newest); - } + } else { + set_field('question_sessions', 'newest', $state->id, 'attemptid', + $state->attempt, 'questionid', $question->id); + } + if (question_state_is_graded($state)) { + // this is also the most recent graded state + if ($newest = get_record('question_sessions', 'attemptid', + $state->attempt, 'questionid', $question->id)) { + $newest->newgraded = $state->id; + $newest->sumpenalty = $state->sumpenalty; + $newest->comment = $state->comment; + update_record('question_sessions', $newest); } } @@ -752,7 +751,9 @@ function question_state_is_graded($state) { * @param object $state */ function question_state_is_closed($state) { - return ($state->event == QUESTION_EVENTCLOSE or $state->event == QUESTION_EVENTCLOSEANDGRADE); + return ($state->event == QUESTION_EVENTCLOSE + or $state->event == QUESTION_EVENTCLOSEANDGRADE + or $state->event == QUESTION_EVENTMANUALGRADE); } @@ -1166,6 +1167,59 @@ function get_question_image($question, $courseid) { } return $img; } + +function question_print_comment_box($question, $state, $attempt, $url) { + global $CFG; + if ($usehtmleditor = can_use_richtext_editor()) { + use_html_editor('comment'); + } + $grade = round($state->last_graded->grade, 3); + echo '
'; + include($CFG->dirroot.'/question/comment.html'); + echo ''; + echo ''; + echo ''; + echo '
'; +} + +function question_process_comment($question, &$state, &$attempt, $comment, $grade) { + + // Update the comment and save it in the database + $state->comment = $comment; + if (!set_field('question_sessions', 'comment', $comment, 'attemptid', $attempt->uniqueid, 'questionid', $question->id)) { + error("Cannot save comment"); + } + + // If the teacher has changed the grade then update the attempt and the state + // The modified attempt is stored to the database, the state not yet but the + // $state->changed flag is set + if (abs($state->last_graded->grade - $grade) > 0.002) { + // the teacher has changed the grade + $attempt->sumgrades = $attempt->sumgrades - $state->last_graded->grade + $grade; + $attempt->timemodified = time(); + if (!update_record('quiz_attempts', $attempt)) { + error('Failed to save the current quiz attempt!'); + } + + $state->raw_grade = $grade; + $state->grade = $grade; + $state->penalty = 0; + $state->timestamp = time(); + // We need to indicate that the state has changed in order for it to be saved + $state->changed = 1; + // We want to update existing state (rather than creating new one) if it + // was itself created by a manual grading event + $state->update = ($state->event == QUESTION_EVENTMANUALGRADE) ? 1 : 0; + $state->event = QUESTION_EVENTMANUALGRADE; + + // Update the last graded state (don't simplify!) + unset($state->last_graded); + $state->last_graded = clone($state); + unset($state->last_graded->changed); + } + +} + /** * Construct name prefixes for question form element names * diff --git a/mod/quiz/comment.php b/mod/quiz/comment.php new file mode 100644 index 0000000000..7fbd831ea5 --- /dev/null +++ b/mod/quiz/comment.php @@ -0,0 +1,87 @@ +quiz)) { + error('Course module is incorrect'); + } + if (! $course = get_record('course', 'id', $quiz->course)) { + error('Course is misconfigured'); + } + + // Teachers are only allowed to comment and grade on closed attempts + if (!($attempt->timefinish > 0)) { + error('Attempt has not closed yet'); + } + + require_login($course->id); + + if (!isteacher($course->id)) { + error('This page is for teachers only'); + } + + // Load question + if (! $question = get_record('question', 'id', $questionid)) { + error('Question for this session is missing'); + } + $question->maxgrade = get_field('quiz_question_instances', 'grade', 'quiz', $quiz->id, 'question', $question->id); + // Some of the questions code is optimised to work with several questions + // at once so it wants the question to be in an array. + $key = $question->id; + $questions[$key] = &$question; + // Add additional questiontype specific information to the question objects. + if (!get_question_options($questions)) { + error("Unable to load questiontype specific question information"); + } + + // Load state + $states = get_question_states($questions, $quiz, $attempt); + // The $states array is indexed by question id but because we are dealing + // with only one question there is only one entry in this array + $state = &$states[$question->id]; + + print_header(); + print_heading(format_string($question->name)); + + //add_to_log($course->id, 'quiz', 'review', "review.php?id=$cm->id&attempt=$attempt->id", "$quiz->id", "$cm->id"); + + if ($data = data_submitted() and confirm_sesskey()) { + // the following will update the state and attempt + question_process_comment($question, $state, $attempt, $data->comment, $data->grade); + // If the state has changed save it and update the quiz grade + if ($state->changed) { + save_question_session($question, $state); + quiz_save_best_grade($quiz); + } + + notify(print_string('changessaved')); + echo '"; + + print_footer(); + exit; + } + + question_print_comment_box($question, $state, $attempt, $CFG->wwwroot.'/mod/quiz/comment.php'); + + print_footer(); + +?> diff --git a/mod/quiz/locallib.php b/mod/quiz/locallib.php index 742b09d113..85ede1d000 100644 --- a/mod/quiz/locallib.php +++ b/mod/quiz/locallib.php @@ -509,8 +509,11 @@ function quiz_get_renderoptions($reviewoptions, $state) { /** * Determine review options */ -function quiz_get_reviewoptions($cmoptions, $attempt, $isteacher=false) { +function quiz_get_reviewoptions($quiz, $attempt, $isteacher=false) { $options->readonly = true; + // Provide the links to the question review and comment script + $options->questionreviewlink = '/mod/quiz/reviewquestion.php'; + if ($isteacher and !$attempt->preview) { // The teacher should be shown everything except during preview when the teachers // wants to see just what the students see @@ -519,27 +522,32 @@ function quiz_get_reviewoptions($cmoptions, $attempt, $isteacher=false) { $options->feedback = true; $options->correct_responses = true; $options->solutions = false; + // Show a link to the comment box only for closed attempts + if ($attempt->timefinish) { + $options->questioncommentlink = '/mod/quiz/comment.php'; + } return $options; } if ((time() - $attempt->timefinish) < 120) { - $options->responses = ($cmoptions->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_RESPONSES) ? 1 : 0; - $options->scores = ($cmoptions->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_SCORES) ? 1 : 0; - $options->feedback = ($cmoptions->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_FEEDBACK) ? 1 : 0; - $options->correct_responses = ($cmoptions->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_ANSWERS) ? 1 : 0; - $options->solutions = ($cmoptions->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_SOLUTIONS) ? 1 : 0; - } else if (!$cmoptions->timeclose or time() < $cmoptions->timeclose) { - $options->responses = ($cmoptions->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_RESPONSES) ? 1 : 0; - $options->scores = ($cmoptions->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_SCORES) ? 1 : 0; - $options->feedback = ($cmoptions->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_FEEDBACK) ? 1 : 0; - $options->correct_responses = ($cmoptions->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_ANSWERS) ? 1 : 0; - $options->solutions = ($cmoptions->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_SOLUTIONS) ? 1 : 0; + $options->responses = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_RESPONSES) ? 1 : 0; + $options->scores = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_SCORES) ? 1 : 0; + $options->feedback = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_FEEDBACK) ? 1 : 0; + $options->correct_responses = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_ANSWERS) ? 1 : 0; + $options->solutions = ($quiz->review & QUIZ_REVIEW_IMMEDIATELY & QUIZ_REVIEW_SOLUTIONS) ? 1 : 0; + } else if (!$quiz->timeclose or time() < $quiz->timeclose) { + $options->responses = ($quiz->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_RESPONSES) ? 1 : 0; + $options->scores = ($quiz->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_SCORES) ? 1 : 0; + $options->feedback = ($quiz->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_FEEDBACK) ? 1 : 0; + $options->correct_responses = ($quiz->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_ANSWERS) ? 1 : 0; + $options->solutions = ($quiz->review & QUIZ_REVIEW_OPEN & QUIZ_REVIEW_SOLUTIONS) ? 1 : 0; } else { - $options->responses = ($cmoptions->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_RESPONSES) ? 1 : 0; - $options->scores = ($cmoptions->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_SCORES) ? 1 : 0; - $options->feedback = ($cmoptions->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_FEEDBACK) ? 1 : 0; - $options->correct_responses = ($cmoptions->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_ANSWERS) ? 1 : 0; - $options->solutions = ($cmoptions->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_SOLUTIONS) ? 1 : 0; + $options->responses = ($quiz->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_RESPONSES) ? 1 : 0; + $options->scores = ($quiz->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_SCORES) ? 1 : 0; + $options->feedback = ($quiz->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_FEEDBACK) ? 1 : 0; + $options->correct_responses = ($quiz->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_ANSWERS) ? 1 : 0; + $options->solutions = ($quiz->review & QUIZ_REVIEW_CLOSED & QUIZ_REVIEW_SOLUTIONS) ? 1 : 0; } + return $options; } diff --git a/mod/quiz/report/grading/report.php b/mod/quiz/report/grading/report.php index 0042d74fcd..a6157ce077 100644 --- a/mod/quiz/report/grading/report.php +++ b/mod/quiz/report/grading/report.php @@ -113,26 +113,14 @@ class quiz_report extends quiz_default_report { // with only one question there is only one entry in this array $state = &$states[$question->id]; - // this is the new response from the teacher - $state->responses = $response; - - // Process the teacher responses - $QTYPES[$question->qtype]->process_teacher_responses($question, $state, $quiz); - - // We need to indicate that the state has changed in order for it to be saved - $state->changed = 1; - // We want to update existing state (rather than creating new one) if it - // was itself created by a manual grading event - $state->update = ($state->event == QUESTION_EVENTMANUALGRADE) ? 1 : 0; - // Go ahead and save - save_question_session($question, $state); - - if ($attempt->sumgrades != $sumgrades) { - set_field('quiz_attempts', 'sumgrades', $sumgrades, 'id', $attempt->id); - } + // the following will update the state and attempt + question_process_comment($question, $state, $attempt, $response['comment'], $response['grade']); - // update user's grade - quiz_save_best_grade($quiz, $attempt->userid); + // If the state has changed save it and update the quiz grade + if ($state->changed) { + save_question_session($question, $state); + quiz_save_best_grade($quiz); + } } notify(get_string('changessaved', 'quiz')); diff --git a/mod/quiz/review.php b/mod/quiz/review.php index 723a1dfd63..ac4e6bf880 100644 --- a/mod/quiz/review.php +++ b/mod/quiz/review.php @@ -235,8 +235,6 @@ $options = quiz_get_reviewoptions($quiz, $attempt, $isteacher); $options->validation = QUESTION_EVENTVALIDATE === $states[$i]->event; $options->history = ($isteacher and !$attempt->preview) ? 'all' : 'graded'; - // Provide the links to the question review script - $options->questionreviewlink = '/mod/quiz/reviewquestion.php'; // Print the question if ($i > 0) { echo "
\n"; diff --git a/mod/quiz/reviewquestion.php b/mod/quiz/reviewquestion.php index 8b6e20e37b..0eefb6e37f 100644 --- a/mod/quiz/reviewquestion.php +++ b/mod/quiz/reviewquestion.php @@ -96,20 +96,25 @@ /// Print heading print_heading(format_string($question->name)); - $instance = get_record('quiz_question_instances', 'quiz', $quiz->id, 'question', $question->id); - $question->instance = $instance->id; - $question->maxgrade = $instance->grade; - $question->name_prefix = 'r'; - $QTYPES[$question->qtype]->get_question_options($question); + $question->maxgrade = get_field('quiz_question_instances', 'grade', 'quiz', $quiz->id, 'question', $question->id); + // Some of the questions code is optimised to work with several questions + // at once so it wants the question to be in an array. + $key = $question->id; + $questions[$key] = &$question; + // Add additional questiontype specific information to the question objects. + if (!get_question_options($questions)) { + error("Unable to load questiontype specific question information"); + } + $session = get_record('question_sessions', 'attemptid', $attempt->uniqueid, 'questionid', $question->id); + $state->sumpenalty = $session->sumpenalty; + $state->comment = $session->comment; restore_question_state($question, $state); $state->last_graded = $state; $options = quiz_get_reviewoptions($quiz, $attempt, $isteacher); $options->validation = ($state->event == QUESTION_EVENTVALIDATE); $options->history = ($isteacher and !$attempt->preview) ? 'all' : 'graded'; - // Provide the links to this question review script - $options->questionreviewlink = '/mod/quiz/reviewquestion.php'; /// Print infobox $table->align = array("right", "left"); diff --git a/question/comment.html b/question/comment.html new file mode 100644 index 0000000000..d3210b3b70 --- /dev/null +++ b/question/comment.html @@ -0,0 +1,26 @@ + + + + + + + + + + +
+ : + + comment); + ?> +
+ : + + /maxgrade; ?> +
+ \ No newline at end of file diff --git a/question/type/question.html b/question/type/question.html index ee1dad4c58..93b7bbe564 100644 --- a/question/type/question.html +++ b/question/type/question.html @@ -8,8 +8,8 @@ - - +
@@ -21,7 +21,16 @@
print_question_grading_details($question, $state, $cmoptions, $options); ?>
- + +
+ +
+
maxgrade; } + + $comment = $state->comment; + $commentlink = ''; + if (isset($options->questioncommentlink)) { + $strcomment = get_string('commentorgrade', 'quiz'); + $commentlink = ''; + } $history = $this->history($question, $state, $number, $cmoptions, $options); @@ -503,11 +511,9 @@ class default_questiontype { get_string('response', 'quiz'), get_string('time'), get_string('score', 'quiz'), - get_string('penalty', 'quiz'), + //get_string('penalty', 'quiz'), get_string('grade', 'quiz'), ); - $table->align = array ('center', 'center', 'left', 'left', 'left', 'left', 'left'); - $table->size = array ('', '', '', '', '', '', ''); $table->width = '100%'; foreach ($states as $st) { $st->responses[''] = $st->answer; @@ -530,7 +536,7 @@ class default_questiontype { $b.$this->response_summary($question, $st).$be, $b.userdate($st->timestamp, get_string('timestr', 'quiz')).$be, $b.round($st->raw_grade, $cmoptions->decimalpoints).$be, - $b.round($st->penalty, $cmoptions->decimalpoints).$be, + //$b.round($st->penalty, $cmoptions->decimalpoints).$be, $b.round($st->grade, $cmoptions->decimalpoints).$be ); } diff --git a/theme/standard/styles_layout.css b/theme/standard/styles_layout.css index 600934080e..9bfa29fcc5 100644 --- a/theme/standard/styles_layout.css +++ b/theme/standard/styles_layout.css @@ -1177,7 +1177,9 @@ body#message-messages { padding: 0 0 0.3em 0.3em; border: 1px solid; } -.que .grading, +.que .grading, +.que .comment, +.que .commentlink, .que .history { float: right; margin: 5px;