I am committing the essay question type contributed by Mark Nielsen, see http://moodle.org/mod/forum/discuss.php?d=25845.

This commit is contained in:
gustav_delius
2005-06-26 16:21:11 +00:00
parent d4e9497a54
commit ed460c8e04
13 changed files with 874 additions and 2 deletions
+21
View File
@@ -839,6 +839,27 @@ function quiz_upgrade($oldversion) {
$db->debug = $olddebug;
}
if ($oldversion < 2005062600) {
modify_database ('', "
CREATE TABLE `prefix_quiz_essay` (
`id` int(10) unsigned NOT NULL auto_increment,
`question` int(10) unsigned NOT NULL default '0',
`answer` varchar(255) NOT NULL default '',
PRIMARY KEY (`id`),
KEY `question` (`question`)
) TYPE=MyISAM COMMENT='Options for essay questions'");
modify_database ('', "
CREATE TABLE `prefix_quiz_essay_states` (
`id` int(10) unsigned NOT NULL auto_increment,
`stateid` int(10) unsigned NOT NULL default '0',
`graded` tinyint(4) unsigned NOT NULL default '0',
`fraction` varchar(10) NOT NULL default '0.0',
`response` text NOT NULL,
PRIMARY KEY (`id`)
) TYPE=MyISAM COMMENT='essay question type specific state information'");
}
return true;
}
+29
View File
@@ -171,6 +171,35 @@ CREATE TABLE prefix_quiz_dataset_items (
-- --------------------------------------------------------
--
-- Table structure for table `mdl_quiz_essay`
--
CREATE TABLE `prefix_quiz_essay` (
`id` int(10) unsigned NOT NULL auto_increment,
`question` int(10) unsigned NOT NULL default '0',
`answer` varchar(255) NOT NULL default '',
PRIMARY KEY (`id`),
KEY `question` (`question`)
) TYPE=MyISAM COMMENT='Options for essay questions';
-- --------------------------------------------------------
--
-- Table structure for table `mdl_quiz_essay_states`
--
CREATE TABLE `prefix_quiz_essay_states` (
`id` int(10) unsigned NOT NULL auto_increment,
`stateid` int(10) unsigned NOT NULL default '0',
`graded` tinyint(4) unsigned NOT NULL default '0',
`fraction` varchar(10) NOT NULL default '0.0',
`response` text NOT NULL,
PRIMARY KEY (`id`)
) TYPE=MyISAM COMMENT='essay question type specific state information';
-- --------------------------------------------------------
--
-- Table structure for table `prefix_quiz_grades`
--
+2 -1
View File
@@ -28,7 +28,8 @@ $QUIZ_QUESTION_TYPE = array ( MULTICHOICE => get_string("multichoice", "quiz")
MATCH => get_string("match", "quiz"),
DESCRIPTION => get_string("description", "quiz"),
RANDOMSAMATCH => get_string("randomsamatch", "quiz"),
MULTIANSWER => get_string("multianswer", "quiz")
MULTIANSWER => get_string("multianswer", "quiz"),
ESSAY => get_string("essay", "quiz")
);
// add remote question types
if ($rqp_types = get_records('quiz_rqp_types')) {
+409
View File
@@ -0,0 +1,409 @@
<?php
// This file allows a teacher to grade essay questions.
// Could be later expanded to change user responses for all question types
# Flow of the file:
# Get variables, run essencial queries, print header and print tabs
# Check for post data submitted. If true, then process data (the data is the grades and comments for essay questions)
# Check for userid, attemptid, or gradeall and for questionid. If found, print out the appropriate essay question attempts
# Switch:
# first case: print out all essay questions in quiz and the number of ungraded attempts
# second case: print out all users and their attempts for a specific essay question
require_once("../../config.php");
require_once("lib.php");
require_once("editlib.php");
require_once($CFG->libdir.'/tablelib.php');
$quizid = required_param('quizid', PARAM_INT); // Course Module ID, or
$action = optional_param('action', 'viewquestions', PARAM_ALPHA);
$questionid = optional_param('questionid', 0, PARAM_INT);
$attemptid = optional_param('attemptid', 0, PARAM_INT);
$gradeall = optional_param('gradeall', 0, PARAM_INT);
$userid = optional_param('userid', 0, PARAM_INT);
if (!empty($questionid)) {
if (! $question = get_record('quiz_questions', 'id', $questionid)) {
error("Question with id $questionid not found");
}
///$number = optional_param('number', 0, PARAM_INT);
}
if (! $quiz = get_record("quiz", "id", $quizid)) {
error("Quiz with id $quizid not found");
}
if (! $course = get_record("course", "id", $quiz->course)) {
error("Course is misconfigured");
}
if (! $cm = get_coursemodule_from_instance("quiz", $quiz->id, $course->id)) {
error("Course Module ID was incorrect");
}
require_login($course->id);
if (!$isteacher = isteacheredit($course->id)) {
error("Only teachers authorized to edit the course '{$course->fullname}' can use this page!");
}
add_to_log($course->id, "quiz", "manualgrading", "grading.php?quizid=$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
# $currentgroup = setup_and_print_groups($course, $groupmode, "attempts.php?id=$cm->id&amp;mode=overview");
# } else {
# $currentgroup = false;
# }
/// Get all students
# if ($currentgroup) {
# $users = get_group_students($currentgroup);
# }
# 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));
}
$strquizzes = get_string("modulenameplural", "quiz");
$strmanualgrading = get_string("manualgrading", "quiz");
print_header_simple("$quiz->name", "",
"<a href=\"index.php?id=$course->id\">$strquizzes</a>
-> <a href=\"view.php?id=$cm->id\">$quiz->name</a> -> $strmanualgrading",
"", "", true);
$currenttab = 'manualgrading';
include('tabs.php');
echo '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>'; // 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);
$QUIZ_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
if (count($keyparts) == 3) { // must have 3 parts to the key
// re-assign to nice variable names for readability
$attemptid = $keyparts[0];
$stateid = $keyparts[1];
$fieldname = $keyparts[2];
$responses[$attemptid.'_'.$stateid][$fieldname] = $response;
}
}
// now go through all of the responses to grade them and save them.
// not totally sure if this process is correct or fully optimized. I need help here!
foreach($responses as $ids => $response) {
// get our necessary ids
$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}quiz_states s,".
" {$CFG->prefix}quiz_newest_states n".
" WHERE s.id = n.newest".
" AND n.attemptid = '$attempt->id'".
" AND n.questionid = $question->id";
$state = get_record_sql($sql);
// restore the state of the question
quiz_restore_state($question, $state);
// this is the new response from the teacher
$state->responses = $response;
// grade the question with the new state made by the teacher
$QUIZ_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
quiz_apply_penalty_and_timelimit($question, $state, $attempt, $quiz);
// want to update session. Also set changed to 1 to trick quiz_save_question_session to save our session
$state->update = 1;
$state->changed = 1;
quiz_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('quiz_newest_states', 'newgraded', 'attemptid', $attempt->id, 'questionid', $questionid);
$sumgrades += get_field('quiz_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);
}
print_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 uniqueid,
qa.id AS attemptid, qa.attempt, qa.timefinish, qa.preview,
u.id AS userid, u.firstname, u.lastname, u.picture ';
$from = 'FROM mdl_user u LEFT JOIN mdl_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
$where = 'WHERE u.id='.$userid.' ';
} 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 ';
$sort = 'ORDER BY u.firstname, u.lastname, qa.attempt ASC';
$attempts = get_records_sql($select.$from.$where.$sort);
echo '<form method="post" action="grading.php">'.
'<input type="hidden" name="quizid" value="'.$quiz->id.'">'.
'<input type="hidden" name="sesskey" value="'.$USER->sesskey.'">'.
'<input type="hidden" name="action" value="viewquestion">'.
'<input type="hidden" name="questionid" value="'.$questionid.'">';
foreach ($attempts as $attempt) {
// retrieve the state
if (!$neweststate = get_record('quiz_newest_states', 'attemptid', $attempt->attemptid, 'questionid', $questionid)) {
error('Invalid attempt and question ids');
}
if (! $state = get_record('quiz_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.'_';
$QUIZ_QTYPES[$question->qtype]->get_question_options($question);
quiz_restore_state($question, $state);
$state->last_graded = $state;
$options = quiz_get_reviewoptions($quiz, $attempt, $isteacher);
$options->validation = ($state->event == QUIZ_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 '<div align="center" width="80%" style="padding:15px;">'.
'<p>'."$attempt->firstname $attempt->lastname: ".
get_string('attempt', 'quiz')." $attempt->attempt".
'</p>';
quiz_print_quiz_question($question, $state, '', $quiz, $options);
echo '<input type="hidden" name="attemptids[]" value="'.$attempt->attemptid.'">'.
'<input type="hidden" name="stateids[]" value="'.$state->id.'">';
echo '</div>';
}
echo '<div align="center"><input type="submit" value="'.get_string('save', 'quiz').'"></div>'.
'</form>';
print_footer($course);
exit();
}
// our 2 different views
// 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
// and all of their attempts at answering the question
switch($action) {
case 'viewquestions':
notify(get_string('essayonly', 'quiz'));
// just a basic table for this...
$table = new stdClass;
$table->head = array(get_string("essayquestions", "quiz"), get_string("ungraded", "quiz"));
$table->align = array("left", "left");
$table->wrap = array("wrap", "wrap");
$table->width = "20%";
$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".
" FROM {$CFG->prefix}quiz_questions q,".
" {$CFG->prefix}quiz_question_instances i".
" WHERE i.quiz = '$quiz->id' AND q.id = i.question".
" AND q.id IN ($questionlist)".
" AND q.qtype = '".ESSAY."'".
" ORDER BY q.name";
if (!$questions = get_records_sql($sql)) {
print_heading(get_string('noessayquestionsfound', 'quiz'));
print_footer($course);
exit();
}
// 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 = "<a href=\"grading.php?quizid=$quiz->id&amp;action=viewquestion&amp;questionid=$question->id\">".
$question->name."</a>";
// determine the number of ungraded attempts (essay question thing only)
$ungraded = 0;
foreach ($attempts as $attempt) {
// grab the state then check if it is graded
if (!$neweststate = get_record('quiz_newest_states', 'attemptid', $attempt->id, 'questionid', $question->id)) {
error('Invalid attempt and question ids');
}
if (!$questionstate = get_record('quiz_essay_states', 'stateid', $neweststate->newest)) {
error('Could not find question state');
}
if (!$questionstate->graded) {
$ungraded++;
}
}
$table->data[] = array($link, $ungraded);
}
print_table($table);
} else {
print_heading(get_string('noattempts', 'quiz'));
}
break;
case 'viewquestion':
// 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/grading.php?quizid='.$quiz->id.'&amp;action=viewquestion&amp;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();
// 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 uniqueid, qa.id AS attemptid, qa.attempt, u.id AS userid, u.firstname, u.lastname, u.picture ';
$from = 'FROM mdl_user u LEFT JOIN mdl_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 ';
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..
} else {
// 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());
} else {
$limit = '';
}
//$number = 1;
// 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
$userlink = "<a href=\"grading.php?quizid=$quiz->id&amp;questionid=$question->id&amp;userid=$attempt->userid\">".
$attempt->firstname.' '.$attempt->lastname.'</a>';
// nab the state of the attempt to see if it is graded or not
if (!$neweststate = get_record('quiz_newest_states', 'attemptid', $attempt->attemptid, 'questionid', $question->id)) {
error('Invalid attempt and question ids');
}
if (!$questionstate = get_record('quiz_essay_states', 'stateid', $neweststate->newest)) {
error('Could not find question state');
}
// change the color of the link based on being graded or not
if (!$questionstate->graded) {
$style = 'style="color:#FF0000"'; // red
} else {
$style = 'style="color:#008000"'; // green
}
// link for the attempt
$attemptlink = "<a $style href=\"grading.php?quizid=$quiz->id&amp;questionid=$question->id&amp;attemptid=$attempt->attemptid\">". // &amp;number=$number
$question->name." attempt $attempt->attempt</a>";
$table->add_data( array($picture, $userlink, $attemptlink) );
}
//$number += $question->length;
}
// grade all and "back" links
$links = "<center><a href=\"grading.php?quizid=$quiz->id&amp;questionid=$questionid&amp;gradeall=1\">".get_string('gradeall', 'quiz').'</a> | '.
"<a href=\"grading.php?quizid=$quiz->id&amp;action=viewquestions\">".get_string('backtoquestionlist', 'quiz').'</a></center>'.
// print everything here
print_heading($question->name);
echo $links;
echo '<div id="tablecontainer">';
$table->print_html();
echo '</div>';
echo $links;
break;
default:
error("Invalid Action");
}
print_footer($course);
?>
+16
View File
@@ -0,0 +1,16 @@
<?php
$string['backtoquestionlist'] = 'Back to Question List';
$string['changessaved'] = 'Grading Changes Saved';
$string['comments'] = 'Comments';
$string['editingessay'] = 'Editing Essay';
$string['essay'] = 'Essay';
$string['essayquestions'] = 'Essay Questions';
$string['gradeall'] = 'Grade All';
$string['gradeessays'] = 'Grade Essays';
$string['manualgrading'] = 'Manual grading';
$string['nocommentsyet'] = 'No comments yet.';
$string['noessayquestionsfound'] = 'No Essay Questions Found';
$string['essayonly'] = 'Manual grading is so far only implemented for essay questions';
$string['numungraded'] = '($a ungraded)';
$string['ungraded'] = 'Ungraded';
?>
+1
View File
@@ -62,6 +62,7 @@ define("NUMERICAL", "8");
define("MULTIANSWER", "9");
define("CALCULATED", "10");
define("RQP", "11");
define("ESSAY", "12");
/**#@-*/
@@ -0,0 +1,16 @@
<?php // $Id$
if (!empty($question->id)) {
$options = get_record("quiz_essay", "question", "$question->id");
}
if (!empty($options->answer)) {
$essayfeedback = get_record("quiz_answers", "id", $options->answer);
} else {
$essayfeedback->feedback = "";
}
print_heading_with_help(get_string("editingessay", "quiz"), "essay", "quiz");
require("$CFG->dirroot/mod/quiz/questiontypes/essay/essay.html");
?>
+95
View File
@@ -0,0 +1,95 @@
<form name="theform" method="post" action="question.php">
<center>
<table cellpadding="5">
<tr valign="top">
<td align="right">
<b><?php print_string("category", "quiz") ?>:</b>
</td>
<td>
<?php quiz_category_select_menu($course->id, true, true, $question->category); ?>
</td>
</tr>
<tr valign="top">
<td align="right">
<b><?php print_string("questionname", "quiz") ?>:</b>
</td>
<td>
<input type="text" name="name" size="50" value="<?php p($question->name) ?>" />
<?php if (isset($err["name"])) formerr($err["name"]); ?>
</td>
</tr>
<tr valign="top">
<td align="right">
<b><?php print_string("question", "quiz") ?>:</b>
<br />
<br />
<br />
<font size="1">
<?php
if ($usehtmleditor) {
helpbutton("richtext", get_string("helprichtext"), "moodle", true, true);
} else {
helpbutton("text", get_string("helptext"), "moodle", true, true);
}
?>
</font>
</td>
<td>
<?php
if (isset($err["questiontext"])) {
formerr($err["questiontext"]);
echo "<br />";
}
print_textarea($usehtmleditor, 15, 60, 630, 300, "questiontext", $question->questiontext);
if ($usehtmleditor) {
echo '<input type="hidden" name="questiontextformat" value="'.FORMAT_HTML.'" />';
} else {
echo "<div align=\"right\">";
print_string("formattexttype");
echo ":&nbsp;";
if (!isset($question->questiontextformat)) {
$question->questiontextformat = FORMAT_MOODLE;
}
choose_from_menu(format_text_menu(), "questiontextformat", $question->questiontextformat, "");
helpbutton("textformat", get_string("helpformatting"));
echo "</div>";
}
?>
</td>
</tr>
<tr valign="top">
<td align="right">
<b><?php print_string("imagedisplay", "quiz") ?>:</b>
</td>
<td>
<?php
if (empty($images)) {
print_string("noimagesyet");
} else {
choose_from_menu($images, "image", "$question->image", get_string("none"),"","");
}
?>
</td>
</tr>
<tr valign="top">
<td align="right">
<b><?php print_string("feedback", "quiz") ?>:</b>
</td>
<td>
<textarea name="feedback" rows="2" cols="50" wrap="virtual"><?php p($essayfeedback->feedback) ?></textarea>
</td>
</tr>
</table>
<input type="hidden" name="fraction" value="0" /> <?php // dont think there would ever be a different value other than 1... ?>
<?php
$QUIZ_QTYPES[$question->qtype]->print_replacement_options($question, $course, $contextquiz);
$QUIZ_QTYPES[$question->qtype]->print_question_form_end($question);
?>
</center>
</form>
Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

@@ -0,0 +1,233 @@
<?php // $Id$
//////////////////
/// ESSAY ///
/////////////////
/// QUESTION TYPE CLASS //////////////////
class quiz_essay_qtype extends quiz_default_questiontype {
function name() {
return 'essay';
}
function get_question_options(&$question) {
// Get additional information from database
// and attach it to the question object
if (!$question->options = get_record('quiz_essay', 'question', $question->id)) {
notify('Error: Missing question options!');
return false;
}
if (!$question->options->answers = get_records('quiz_answers', 'question',
$question->id)) {
notify('Error: Missing question answers!');
return false;
}
return true;
}
function save_question_options($question) {
if ($answer = get_record("quiz_answers", "question", $question->id)) {
// Existing answer, so reuse it
$answer->answer = $question->feedback;
$answer->feedback = $question->feedback;
$answer->fraction = $question->fraction;
if (!update_record("quiz_answers", $answer)) {
$result->error = "Could not update quiz answer!";
return $result;
}
} else {
unset($answer);
$answer->question = $question->id;
$answer->answer = $question->feedback;
$answer->feedback = $question->feedback;
$answer->fraction = $question->fraction;
if (!$answer->id = insert_record("quiz_answers", $answer)) {
$result->error = "Could not insert quiz answer!";
return $result;
}
}
if ($options = get_record("quiz_essay", "question", $question->id)) {
// No need to do anything, since the answer IDs won't have changed
// But we'll do it anyway, just for robustness
$options->answer = $answer->id;
if (!update_record("quiz_essay", $options)) {
$result->error = "Could not update quiz essay options! (id=$options->id)";
return $result;
}
} else {
unset($options);
$options->question = $question->id;
$options->answer = $answer->id;
if (!insert_record("quiz_essay", $options)) {
$result->error = "Could not insert quiz essay options!";
return $result;
}
}
return true;
}
function print_question_formulation_and_controls(&$question, &$state, $quiz, $options) {
$answers = &$question->options->answers;
//$correctanswers = $this->get_correct_responses($question, $state); // no correct answers ;)
$readonly = empty($options->readonly) ? '' : 'disabled="disabled"';
$nameprefix = $question->name_prefix;
/// Print question text and media
echo format_text($question->questiontext,
$question->questiontextformat,
NULL, $quiz->course);
quiz_print_possible_question_image($quiz->id, $question);
/// Print input controls
$stranswer = get_string("answer", "quiz");
$strcomment = get_string("comments", "quiz");
$usehtmleditor = can_use_html_editor();
// this prints out the student response box
if (isset($state->responses[''])) {
// security problem. responses[''] is never cleaned before it is sent to the db (I think)
$value = clean_param($state->responses[''], PARAM_CLEANHTML);
} else {
$value = "";
}
$inputname = $nameprefix;
echo "<p>$stranswer: ".
'<div style="padding-left: 30px;">';
if (empty($options->readonly)) {
// the student needs to type in their answer so print out a text editor
print_textarea($usehtmleditor, 18, 80, 630, 400, $inputname, $value);
use_html_editor($inputname);
} else {
// it is read only, so just format the students answer and output it
echo format_text($value);
echo '<input type="hidden" name="'.$inputname.'" value="'.htmlSpecialChars($value).'">'; // need hidden one for grading
}
echo '</div></p>';
if (isset($state->responses['response'])) {
$value = $state->responses['response'];
} else {
$value = "";
}
$inputname = $nameprefix.'response';
if(!empty($options->regrade)) { // special option set in regrade.php. This means we want to grade the essay question
// print out a field for the teacher to add a comment
echo "<p>$strcomment: ".
'<div style="padding-left: 30px;">';
print_textarea($usehtmleditor, 18, 80, 630, 400, $inputname, $value);
use_html_editor($inputname);
echo '</div></p><br />';
// dropdown for score... for the fraction
$grades = array(1,0.9,0.8,0.75,0.70,0.66666,0.60,0.50,0.40,0.33333,0.30,0.25,0.20,0.16666,0.142857,0.10,0.05,0);
foreach ($grades as $grade) {
$percentage = 100 * $grade;
$neggrade = -$grade;
$gradeoptions["$grade"] = "$percentage %";
$gradeoptionsfull["$grade"] = "$percentage %";
$gradeoptionsfull["$neggrade"] = -$percentage." %";
}
$gradeoptionsfull["0"] = $gradeoptions["0"] = get_string("none");
print_string("grade");
echo ":&nbsp;";
choose_from_menu($gradeoptions, $nameprefix."fraction", $state->responses['fraction'],"");
} else if (!empty($options->readonly)) {
//read only so format the comment and print it out
echo "<p>$strcomment: ".
'<div style="padding-left: 30px;">';
if (empty($value)) { // no comment yet
echo format_text(get_string('nocommentsyet', 'quiz'));
} else {
echo format_text($value);
}
echo '</div></p>';
}
// feedback
if ($options->feedback) {
foreach ($answers as $answer) {
quiz_print_comment("<p align=\"right\">$answer->feedback</p>");
}
}
}
function grade_responses(&$question, &$state, $quiz) {
$state->raw_grade = 0;
// if a fraction is submitted, then we use it, otherwise the raw grade is 0
if (isset($state->responses['fraction'])) {
$state->raw_grade = $state->responses['fraction'];
$state->options->graded = 1;
}
if (empty($state->raw_grade)) {
$state->raw_grade = 0;
}
// Make sure we don't assign negative or too high marks
$state->raw_grade = min(max((float) $state->raw_grade,
0.0), 1.0) * $question->maxgrade;
$state->penalty = $question->penalty * $question->maxgrade; // should be no penalty for essays
return true;
}
function create_session_and_responses(&$question, &$state, $quiz, $attempt) {
$state->options->graded = 0; // our flag to indicated wheather an essay has been graded or not
$state->responses['fraction'] = 0; // this fraction is used for grading. The teacher sets it while grading
$state->responses['response'] = ''; // this is teacher response to the students essay
return true;
}
function restore_session_and_responses(&$question, &$state) {
if (!$options = get_record('quiz_essay_states', 'stateid', $state->id)) {
return false;
}
$state->options->graded = $options->graded;
$state->responses['fraction'] = $options->fraction;
$state->responses['response'] = $options->response;
return true;
}
function save_session_and_responses(&$question, &$state) {
$options->stateid = $state->id;
$options->graded = $state->options->graded;
if (isset($state->responses['fraction'])) {
$options->fraction = $state->responses['fraction'];
}
if (isset($state->responses['response'])) {
$options->response = addslashes( clean_param($state->responses['response'], PARAM_CLEANHTML) );
}
if (isset($state->update)) {
if (!$options->id = get_field('quiz_essay_states', 'id', 'stateid', $state->id)) {
return false;
}
if (!update_record('quiz_essay_states', $options)) {
return false;
}
} else {
if (!insert_record('quiz_essay_states', $options)) {
return false;
}
}
return true;
}
}
//// END OF CLASS ////
//////////////////////////////////////////////////////////////////////////
//// INITIATION - Without this line the question type is not in use... ///
//////////////////////////////////////////////////////////////////////////
$QUIZ_QTYPES[ESSAY] = new quiz_essay_qtype();
?>
+50
View File
@@ -54,4 +54,54 @@ body#mod-quiz-report table#itemanalysis .qname {
color: green !important;
}
/* manual grading */
body#mod-quiz-grading table#grading
{
width: 80%;
margin: auto;
}
body#mod-quiz-grading table#grading
{
margin: 20px auto;
}
body#mod-quiz-grading table#grading .header,
body#mod-quiz-grading table#grading .cell
{
padding: 4px;
}
body#mod-quiz-grading table#grading .header .commands
{
display: inline;
}
body#mod-quiz-grading table#grading .picture
{
width: 40px;
}
body#mod-quiz-grading table#grading td
{
border-left-width: 1px;
border-right-width: 1px;
border-left-style: solid;
border-right-style: solid;
vertical-align: bottom;
}
body#mod-quiz-grading table#grading .header {
text-align: left;
}
body#mod-quiz-grading table#grading .picture {
text-align: center !important;
}
body#mod-quiz-grading .controls {
text-align: center;
}
body#mod-quiz-grading table#grading td {
border-color: #dddddd;
}
body#mod-quiz-grading table#grading .r1 {
background-color: #eeeeee;
}
/* grading */
+1
View File
@@ -25,6 +25,7 @@
$row[] = new tabobject('preview', "attempt.php?q=$quiz->id", get_string('preview', 'quiz'));
if (isteacheredit($course->id)) {
$row[] = new tabobject('edit', "edit.php?quizid=$quiz->id", get_string('editquiz', 'quiz'));
$row[] = new tabobject('manualgrading', "grading.php?quizid=$quiz->id", get_string("manualgrading", "quiz"));
//$row[] = new tabobject('update', "$CFG->wwwroot/course/mod.php?update=$cm->id&amp;sesskey=$USER->sesskey", get_string('updatethis', '', get_string('modulename', 'quiz')));
}
+1 -1
View File
@@ -5,7 +5,7 @@
// This fragment is called by moodle_needs_upgrading() and /admin/index.php
////////////////////////////////////////////////////////////////////////////////
$module->version = 2005060301; // The (date) version of this module
$module->version = 2005062600; // The (date) version of this module
$module->requires = 2005021600; // Requires this Moodle version
$module->cron = 0; // How often should cron check this module (seconds)?