From: gustav_delius Date: Thu, 6 Apr 2006 16:45:14 +0000 (+0000) Subject: Some code cleanup, relying more on the functions from questionlib.php. Not currently... X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=80bbc7d7d1ec65873bc62415d0db1fe99e3e6519;p=moodle.git Some code cleanup, relying more on the functions from questionlib.php. Not currently functional, awaiting the central manual grading feature. --- diff --git a/mod/quiz/report/grading/report.php b/mod/quiz/report/grading/report.php index fa8750e2c0..0042d74fcd 100644 --- a/mod/quiz/report/grading/report.php +++ b/mod/quiz/report/grading/report.php @@ -1,6 +1,6 @@ -print_header_and_tabs($cm, $course, $quiz, $reportmode="grading"); + + notice('The manual grading is temporarily disabled during development work', $CFG->wwwroot.'/mod/quiz/report.php?q='.$quiz->id); if (!empty($questionid)) { if (! $question = get_record('question', 'id', $questionid)) { error("Question with id $questionid not found"); } - ///$number = optional_param('number', 0, PARAM_INT); + $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. The array key + // must be the question id. + $key = $question->id; + $questions[$key] = &$question; + + // We need to add additional questiontype specific information to + // the question objects. + if (!get_question_options($questions)) { + error("Unable to load questiontype specific question information"); + } + // This will have extended the question object so that it now holds + // all the information about the questions that may be needed later. } - + add_to_log($course->id, "quiz", "manualgrading", "report.php?mode=grading&q=$quiz->id", "$quiz->id", "$cm->id"); - + /// GROUP CODE FROM ATTEMPTS.PHP no sure how to use just yet... need to update later perhaps /// Check to see if groups are being used in this quiz # if ($groupmode = groupmode($course, $cm)) { // Groups are being used @@ -44,7 +60,7 @@ class quiz_report extends quiz_default_report { # } else { # $currentgroup = false; # } - + /// Get all students # if ($currentgroup) { # $users = get_group_students($currentgroup); @@ -52,23 +68,20 @@ class quiz_report extends quiz_default_report { # else { $users = get_course_students($course->id); # } - + if(empty($users)) { print_heading(get_string("noattempts", "quiz")); return true; } else { // for sql queries - $userids = implode(', ', array_keys($users)); + $userids = implode(', ', array_keys($users)); } - + echo ''; // for overlib - + if ($data = data_submitted()) { // post data submitted, process it confirm_sesskey(); - - $question->maxgrade = get_field('quiz_question_instances', 'grade', 'quiz', $quiz->id, 'question', $question->id); - $QTYPES[$question->qtype]->get_question_options($question); - + // first, process all the data to extract the teacher's new responses for the question(s) foreach ($data as $key => $response) { $keyparts = explode('_', $key); // valid keys are in this format: attemptid_stateid_fieldname @@ -77,7 +90,7 @@ class quiz_report extends quiz_default_report { $attemptid = $keyparts[0]; $stateid = $keyparts[1]; $fieldname = $keyparts[2]; - + $responses[$attemptid.'_'.$stateid][$fieldname] = $response; } } @@ -88,63 +101,48 @@ class quiz_report extends quiz_default_report { $ids = explode('_', $ids); $attemptid = $ids[0]; $stateid = $ids[1]; - + // get our attempt if (! $attempt = get_record('quiz_attempts', 'id', $attemptid)) { error('No such attempt ID exists'); - } - - // get the state - $statefields = 'n.questionid as question, s.*, n.sumpenalty'; - $sql = "SELECT $statefields". - " FROM {$CFG->prefix}question_states s,". - " {$CFG->prefix}question_sessions n". - " WHERE s.id = n.newest". - " AND n.attemptid = '$attempt->uniqueid'". - " AND n.questionid = $question->id"; - $state = get_record_sql($sql); - - // restore the state of the question - restore_question_state($question, $state); - + } + + // Load the state for this attempt (The questions array was created earlier) + $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]; + // this is the new response from the teacher $state->responses = $response; - - // grade the question with the new state made by the teacher - $QTYPES[$question->qtype]->grade_responses($question, $state, $quiz); - - // finalize the grade - $state->last_graded->grade = 0; // we dont want the next function to care about the last grade - question_apply_penalty_and_timelimit($question, $state, $attempt, $quiz); - - // want to update session. Also set changed to 1 to trick save_question_session to save our session - $state->update = 1; + + // 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); - - // method for changing sumgrades from report type regrade. Thanks! - $sumgrades = 0; - $questionids = explode(',', quiz_questions_in_quiz($attempt->layout)); - foreach($questionids as $questionid) { - $lastgradedid = get_field('question_sessions', 'newgraded', 'attemptid', $attempt->uniqueid, 'questionid', $questionid); - $sumgrades += get_field('question_states', 'grade', 'id', $lastgradedid); - } - + if ($attempt->sumgrades != $sumgrades) { set_field('quiz_attempts', 'sumgrades', $sumgrades, 'id', $attempt->id); } - + // update user's grade quiz_save_best_grade($quiz, $attempt->userid); } notify(get_string('changessaved', 'quiz')); + } else if ( ( !empty($attemptid) or !empty($gradeall) or !empty($userid)) and !empty($questionid) ) { // need attemptid and questionid or gradeall and a questionid // this sql joins the attempts table and the user table - $select = 'SELECT '.$db->Concat('u.id', '\'#\'', $db->IfNull('qa.attempt', '0')).' AS userattemptid, - qa.id AS attemptid, qa.uniqueid, qa.attempt, qa.timefinish, qa.preview, + $select = 'SELECT '.$db->Concat('u.id', '\'#\'', $db->IfNull('qa.attempt', '0')).' AS userattemptid, + qa.id AS attemptid, qa.uniqueid, qa.attempt, qa.timefinish, qa.preview, u.id AS userid, u.firstname, u.lastname, u.picture '; $from = 'FROM '.$CFG->prefix.'user u LEFT JOIN '.$CFG->prefix.'quiz_attempts qa ON (u.id = qa.userid AND qa.quiz = '.$quiz->id.') '; - + if ($gradeall) { // get all user attempts $where = 'WHERE u.id IN ('.implode(',', array_keys($users)).') '; } else if ($userid) { // get all the attempts for a specific user @@ -152,70 +150,58 @@ class quiz_report extends quiz_default_report { } else { // get a specific attempt $where = 'WHERE qa.id='.$attemptid.' '; } - + $where .= 'AND '.$db->IfNull('qa.attempt', '0').' != 0 '; - $where .= 'AND '.$db->IfNull('qa.timefinish', '0').' != 0 '; + $where .= 'AND '.$db->IfNull('qa.timefinish', '0').' != 0 '; $sort = 'ORDER BY u.firstname, u.lastname, qa.attempt ASC'; $attempts = get_records_sql($select.$from.$where.$sort); - + echo '
'. ''. ''. ''. ''. - ''; - + ''; + foreach ($attempts as $attempt) { - // retrieve the state - if (!$neweststate = get_record('question_sessions', 'attemptid', $attempt->uniqueid, 'questionid', $questionid)) { - error("Can not find newest states for attempt $attempt->uniqueid for question $questionid"); - } - if (! $state = get_record('question_states', 'id', $neweststate->newest)) { - error('Invalid state id'); - } - - // get everything ready for the question to be printed - $instance = get_record('quiz_question_instances', 'quiz', $quiz->id, 'question', $question->id); - $question->instance = $instance->id; - $question->maxgrade = $instance->grade; - $question->name_prefix = $attempt->attemptid.'_'.$state->id.'_'; - $QTYPES[$question->qtype]->get_question_options($question); - - restore_question_state($question, $state); - $state->last_graded = $state; - + + // Load the state for this attempt (The questions array was created earlier) + $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]; + $options = quiz_get_reviewoptions($quiz, $attempt, true); - $options->validation = ($state->event == QUESTION_EVENTVALIDATE); // not sure what this is //$options->history = 'all'; // had this on, but seemed confusing for this - - // IF this code is expanded to manually regrade any question type, then - // readonly would be set to 0 and the essay question would have to be - // updated. Also, regrade would most likly be tossed. + $options->readonly = 1; $options->regrade = 1; - + // print the user name, attempt count, the question, and some more hidden fields echo '
'. '

'."$attempt->firstname $attempt->lastname: ". get_string('attempt', 'quiz')." $attempt->attempt". '

'; - + print_question($question, $state, '', $quiz, $options); echo ''. ''; echo '
'; + + // TODO: This is where the code for printing the comment box and grade selector + // should go. } echo '
'. '
'; print_footer($course); exit(); } - + // our 2 different views - // the first one displays all of the essay questions in the quiz + // the first one displays all of the essay questions in the quiz // with the number of ungraded attempts for each essay question - - // the second view displays the users who have answered the essay question + + // the second view displays the users who have answered the essay question // and all of their attempts at answering the question switch($action) { case 'viewquestions': @@ -226,9 +212,9 @@ class quiz_report extends quiz_default_report { $table->align = array("left", "left"); $table->wrap = array("wrap", "wrap"); $table->width = "20%"; - $table->size = array("*", "*"); + $table->size = array("*", "*"); $table->data = array(); - + // get the essay questions $questionlist = quiz_questions_in_quiz($quiz->questions); $sql = "SELECT q.*, i.grade AS maxgrade, i.id AS instance". @@ -246,10 +232,12 @@ class quiz_report extends quiz_default_report { // get all the finished attempts by the users if ($attempts = get_records_select('quiz_attempts', "quiz = $quiz->id and timefinish > 0 and userid IN ($userids)", 'userid, attempt')) { foreach($questions as $question) { - + $link = "id&action=viewquestion&questionid=$question->id\">". $question->name.""; // determine the number of ungraded attempts (essay question thing only) + // TODO: This should be done with more efficient SQL + // It should use the event field of the newest graded state $ungraded = 0; foreach ($attempts as $attempt) { // grab the state then check if it is graded @@ -263,7 +251,7 @@ class quiz_report extends quiz_default_report { $ungraded++; } } - + $table->data[] = array($link, $ungraded); } print_table($table); @@ -275,43 +263,43 @@ class quiz_report extends quiz_default_report { // gonna use flexible_table (first time!) $tablecolumns = array('picture', 'fullname', 'attempt'); $tableheaders = array('', get_string('fullname'), get_string("attempts", "quiz")); - + $table = new flexible_table('mod-quiz-report-grading'); - + $table->define_columns($tablecolumns); $table->define_headers($tableheaders); $table->define_baseurl($CFG->wwwroot.'/mod/quiz/report.php?mode=grading&q='.$quiz->id.'&action=viewquestion&questionid='.$question->id); - + $table->sortable(true); $table->initialbars(count($users)>20); // will show initialbars if there are more than 20 users $table->pageable(true); - + $table->column_suppress('fullname'); $table->column_suppress('picture'); - + $table->column_class('picture', 'picture'); - + // attributes in the table tag $table->set_attribute('cellspacing', '0'); $table->set_attribute('id', 'grading'); $table->set_attribute('class', 'generaltable generalbox'); $table->set_attribute('align', 'center'); $table->set_attribute('width', '50%'); - + // get it ready! - $table->setup(); - + $table->setup(); + // this sql is a join of the attempts table and the user table. I do this so I can sort by user name and attempt number (not id) $select = 'SELECT '.$db->Concat('u.id', '\'#\'', $db->IfNull('qa.attempt', '0')).' AS userattemptid, qa.id AS attemptid, qa.uniqueid, qa.attempt, u.id AS userid, u.firstname, u.lastname, u.picture '; $from = 'FROM '.$CFG->prefix.'user u LEFT JOIN '.$CFG->prefix.'quiz_attempts qa ON (u.id = qa.userid AND qa.quiz = '.$quiz->id.') '; $where = 'WHERE u.id IN ('.implode(',', array_keys($users)).') '; $where .= 'AND '.$db->IfNull('qa.attempt', '0').' != 0 '; - $where .= 'AND '.$db->IfNull('qa.timefinish', '0').' != 0 '; - + $where .= 'AND '.$db->IfNull('qa.timefinish', '0').' != 0 '; + if($table->get_sql_where()) { // forgot what this does $where .= 'AND '.$table->get_sql_where(); } - + // sorting of the table if($sort = $table->get_sql_sort()) { $sort = 'ORDER BY '.$sort; // seems like I would need to have u. or qa. infront of the ORDER BY attribues... but seems to work.. @@ -319,11 +307,11 @@ class quiz_report extends quiz_default_report { // my default sort rule $sort = 'ORDER BY u.firstname, u.lastname, qa.attempt ASC'; } - + // set up the pagesize $total = count_records_sql('SELECT COUNT(DISTINCT('.$db->Concat('u.id', '\'#\'', $db->IfNull('qa.attempt', '0')).')) '.$from.$where); $table->pagesize(10, $total); - + // this is for getting the correct records for a given page if($table->get_page_start() !== '' && $table->get_page_size() !== '') { $limit = ' '.sql_paging_limit($table->get_page_start(), $table->get_page_size()); @@ -334,18 +322,19 @@ class quiz_report extends quiz_default_report { // get the attempts and process them if ($attempts = get_records_sql($select.$from.$where.$sort.$limit)) { foreach($attempts as $attempt) { - + $picture = print_user_picture($attempt->userid, $course->id, $attempt->picture, false, true); - - // link here... grades all for this student + + // link here... grades all for this student $userlink = "id&questionid=$question->id&userid=$attempt->userid\">". $attempt->firstname.' '.$attempt->lastname.''; - + // nab the state of the attempt to see if it is graded or not + // TODO: should be changed to use the event field if (!$neweststate = get_record('question_sessions', 'attemptid', $attempt->uniqueid, 'questionid', $question->id)) { error("Can not find newest states for attempt $attempt->uniqueid for question $questionid"); } - + if (!$questionstate = get_record('question_essay_states', 'stateid', $neweststate->newest)) { error('Could not find question state'); } @@ -355,27 +344,27 @@ class quiz_report extends quiz_default_report { } else { $style = 'style="color:#008000"'; // green } - + // link for the attempt $attemptlink = "id&questionid=$question->id&attemptid=$attempt->attemptid\">". // &number=$number $question->name." attempt $attempt->attempt"; - + $table->add_data( array($picture, $userlink, $attemptlink) ); } //$number += $question->length; } - + // grade all and "back" links $links = "
id&questionid=$questionid&gradeall=1\">".get_string('gradeall', 'quiz').' | '. "id&action=viewquestions\">".get_string('backtoquestionlist', 'quiz').'
'. - + // print everything here print_heading($question->name); echo $links; echo '
'; $table->print_html(); echo '
'; - echo $links; + echo $links; break; default: error("Invalid Action");