Improved handling of event types so that now graded states can always be distinguished from ungraded ones.

This commit is contained in:
gustav_delius
2006-03-19 18:28:29 +00:00
parent 43a602a7a6
commit f30bbcaf5b
11 changed files with 93 additions and 52 deletions
+2
View File
@@ -159,6 +159,8 @@ $string['event2'] = 'Save';
$string['event3'] = 'Grade';
$string['event5'] = 'Validate';
$string['event6'] = 'Close';
$string['event7'] = 'Submit';
$string['event8'] = 'Close';
$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';
+59 -44
View File
@@ -22,14 +22,15 @@
/**#@+
* The different types of events that can create question states
*/
define('QUESTION_EVENTOPEN', '0');
define('QUESTION_EVENTNAVIGATE', '1');
define('QUESTION_EVENTSAVE', '2');
define('QUESTION_EVENTGRADE', '3');
define('QUESTION_EVENTDUPLICATEGRADE', '4');
define('QUESTION_EVENTVALIDATE', '5');
define('QUESTION_EVENTCLOSE', '6');
define('QUESTION_EVENTSUBMIT', '7');
define('QUESTION_EVENTOPEN', '0'); // The state was created by Moodle
define('QUESTION_EVENTNAVIGATE', '1'); // The responses were saved because the student navigated to another page (this is not currently used)
define('QUESTION_EVENTSAVE', '2'); // The student has requested that the responses should be saved but not submitted or validated
define('QUESTION_EVENTGRADE', '3'); // Moodle has graded the responses. A SUBMIT event can be changed to a GRADE event by Moodle.
define('QUESTION_EVENTDUPLICATE', '4'); // The responses submitted were the same as previously
define('QUESTION_EVENTVALIDATE', '5'); // The student has requested a validation. This causes the responses to be saved as well, but not graded.
define('QUESTION_EVENTCLOSEANDGRADE', '6'); // Moodle has graded the responses. A CLOSE event can be changed to a CLOSEANDGRADE event by Moodle.
define('QUESTION_EVENTSUBMIT', '7'); // The student response has been submitted but it has not yet been marked
define('QUESTION_EVENTCLOSE', '8'); // The response has been submitted and the session has been closed, either because the student requested it or because Moodle did it (e.g. because of a timelimit). The responses have not been graded.
/**#@-*/
/**#@+
@@ -275,7 +276,6 @@ function get_question_states(&$questions, $cmoptions, $attempt) {
$states[$i]->last_graded = $gradedstates[$i];
} else {
$states[$i]->last_graded = clone($states[$i]);
$states[$i]->last_graded->responses = array('' => '');
}
} else {
// Create a new state object
@@ -445,7 +445,17 @@ function save_question_session(&$question, &$state) {
* @param object $state
*/
function question_state_is_graded($state) {
return ($state->event == QUESTION_EVENTGRADE or $state->event == QUESTION_EVENTCLOSE);
return ($state->event == QUESTION_EVENTGRADE or $state->event == QUESTION_EVENTCLOSEANDGRADE);
}
/**
* Determines whether a state has been closed by looking at the event field
*
* @return boolean true if the state has been closed
* @param object $state
*/
function question_state_is_closed($state) {
return ($state->event == QUESTION_EVENTCLOSE or $state->event == QUESTION_EVENTCLOSEANDGRADE);
}
@@ -479,7 +489,7 @@ function question_extract_responses($questions, $responses, $defaultevent) {
if ($key === 'validate') {
$actions[$quid]->event = QUESTION_EVENTVALIDATE;
} else if ($key === 'mark') {
$actions[$quid]->event = QUESTION_EVENTGRADE;
$actions[$quid]->event = QUESTION_EVENTSUBMIT;
} else {
$actions[$quid]->event = $defaultevent;
}
@@ -537,10 +547,11 @@ function regrade_question_in_attempt($question, $attempt, $cmoptions, $verbose=f
if (((count($states) - 1) === $j) && ($attempt->timefinish > 0)) {
$action->event = QUESTION_EVENTCLOSE;
// Grade instead of closing, question_process_responses will then
// work out whether to close it
} else if (QUESTION_EVENTCLOSE == $states[$j]->event) {
$action->event = QUESTION_EVENTGRADE;
// Change event to submit so that it will be reprocessed
} else if (QUESTION_EVENTCLOSE == $states[$j]->event
or QUESTION_EVENTGRADE == $states[$j]->event
or QUESTION_EVENTCLOSEANDGRADE == $states[$j]->event) {
$action->event = QUESTION_EVENTSUBMIT;
// By default take the event that was saved in the database
} else {
@@ -605,14 +616,15 @@ function question_process_responses(&$question, &$state, $action, $cmoptions, &$
unset($action->responses['mark'], $action->responses['validate']);
// Check the question session is still open
if (QUESTION_EVENTCLOSE == $state->event) {
if (question_state_is_closed($state)) {
return true;
}
// If $action->event is not set that implies saving
if (! isset($action->event)) {
$action->event = QUESTION_EVENTSAVE;
}
// Check if we are grading the question; compare against last graded
// If submitted then compare against last graded
// responses, not last given responses in this case
if (question_isgradingevent($action->event)) {
$state->responses = $state->last_graded->responses;
@@ -622,6 +634,8 @@ function question_process_responses(&$question, &$state, $action, $cmoptions, &$
$sameresponses = (($state->responses == $action->responses) or
($state->responses == array(''=>'') && array_keys(array_count_values($action->responses))===array('')));
// If the response has not been changed then we do not have to process it again
// unless the attempt is closing or validation is requested
if ($sameresponses and QUESTION_EVENTCLOSE != $action->event
and QUESTION_EVENTVALIDATE != $action->event) {
return true;
@@ -646,11 +660,10 @@ function question_process_responses(&$question, &$state, $action, $cmoptions, &$
// Grade the response but don't update the overall grade
$QTYPES[$question->qtype]->grade_responses(
$question, $state, $cmoptions);
// Force the event to save or validate (even if the grading caused the
// state to close)
// Don't allow the processing to change the event type
$state->event = $action->event;
} else if (QUESTION_EVENTGRADE == $action->event) {
} else if (QUESTION_EVENTSUBMIT == $action->event) {
// Work out if the current responses (or equivalent responses) were
// already given in
@@ -658,33 +671,35 @@ function question_process_responses(&$question, &$state, $action, $cmoptions, &$
// b. any other graded attempt
if($QTYPES[$question->qtype]->compare_responses(
$question, $state, $state->last_graded)) {
$state->event = QUESTION_EVENTDUPLICATEGRADE;
$state->event = QUESTION_EVENTDUPLICATE;
} else {
if ($cmoptions->optionflags & QUIZ_IGNORE_DUPRESP) {
/* Walk back through the previous graded states looking for
one where the responses are equivalent to the current
responses. If such a state is found, set the current grading
details to those of that state and set the event to
QUESTION_EVENTDUPLICATEGRADE */
QUESTION_EVENTDUPLICATE */
question_search_for_duplicate_responses($question, $state);
}
// If we did not find a duplicate, perform grading
if (QUESTION_EVENTDUPLICATEGRADE != $state->event) {
// Decrease sumgrades by previous grade and then later add new grade
$attempt->sumgrades -= (float)$state->last_graded->grade;
$QTYPES[$question->qtype]->grade_responses(
$question, $state, $cmoptions);
// Calculate overall grade using correct penalty method
question_apply_penalty_and_timelimit($question, $state, $attempt, $cmoptions);
// Update the last graded state (don't simplify!)
unset($state->last_graded);
$state->last_graded = clone($state);
unset($state->last_graded->changed);
$attempt->sumgrades += (float)$state->last_graded->grade;
}
}
// If we did not find a duplicate, perform grading
if (QUESTION_EVENTDUPLICATE != $state->event) {
// Decrease sumgrades by previous grade and then later add new grade
$attempt->sumgrades -= (float)$state->last_graded->grade;
$QTYPES[$question->qtype]->grade_responses(
$question, $state, $cmoptions);
// Calculate overall grade using correct penalty method
question_apply_penalty_and_timelimit($question, $state, $attempt, $cmoptions);
// Update the last graded state (don't simplify!)
unset($state->last_graded);
$state->last_graded = clone($state);
unset($state->last_graded->changed);
$attempt->sumgrades += (float)$state->last_graded->grade;
}
} else if (QUESTION_EVENTCLOSE == $action->event) {
// decrease sumgrades by previous grade and then later add new grade
$attempt->sumgrades -= (float)$state->last_graded->grade;
@@ -696,8 +711,6 @@ function question_process_responses(&$question, &$state, $action, $cmoptions, &$
// Calculate overall grade using correct penalty method
question_apply_penalty_and_timelimit($question, $state, $attempt, $cmoptions);
}
// Force the state to close (as the attempt is closing)
$state->event = QUESTION_EVENTCLOSE;
// Update the last graded state (don't simplify!)
unset($state->last_graded);
@@ -715,7 +728,7 @@ function question_process_responses(&$question, &$state, $action, $cmoptions, &$
* Determine if event requires grading
*/
function question_isgradingevent($event) {
return (QUESTION_EVENTGRADE == $event || QUESTION_EVENTCLOSE == $event);
return (QUESTION_EVENTSUBMIT == $event || QUESTION_EVENTCLOSE == $event);
}
/**
@@ -725,6 +738,8 @@ function question_isgradingevent($event) {
* to ignore the marking request for the current response. However this
* check against all previous graded responses is only performed if
* the QUIZ_IGNORE_DUPRESP bit in $cmoptions->optionflags is set
* If the current response is a duplicate of a previously graded response then
* $STATE->event is set to QUESTION_EVENTDUPLICATE.
* @return boolean Indicates if a state with duplicate responses was
* found.
* @param object $question
@@ -743,12 +758,12 @@ function question_search_for_duplicate_responses(&$question, &$state) {
$question, $oldstate)) {
if(!$QTYPES[$question->qtype]->compare_responses(
$question, $state, $oldstate)) {
$state->event = QUESTION_EVENTDUPLICATEGRADE;
$state->event = QUESTION_EVENTDUPLICATE;
break;
}
}
}
return (QUESTION_EVENTDUPLICATEGRADE == $state->event);
return (QUESTION_EVENTDUPLICATE == $state->event);
}
/**
@@ -771,7 +786,7 @@ function question_search_for_duplicate_responses(&$question, &$state) {
* for incorrect earlier responses are subtracted.
*/
function question_apply_penalty_and_timelimit(&$question, &$state, $attempt, $cmoptions) {
// deal with penaly
// deal with penalty
if ($cmoptions->penaltyscheme) {
$state->grade = $state->raw_grade - $state->sumpenalty;
$state->sumpenalty += (float) $state->penalty;
@@ -173,12 +173,13 @@ class question_essay_qtype extends quiz_default_questiontype {
function grade_responses(&$question, &$state, $cmoptions) {
$state->raw_grade = 0;
// if a fraction is submitted, then we use it, otherwise the raw grade is 0
if (isset($state->responses['fraction'])) {
if ($state->responses['fraction']) {
$state->raw_grade = $state->responses['fraction'];
$state->options->graded = 1;
// mark the state as graded
$state->event = ($state->event == QUESTION_EVENTCLOSE) ? QUESTION_EVENTCLOSEANDGRADE : QUESTION_EVENTGRADE;
} else {
$state->raw_grade = 0;
$state->event = QUESTION_EVENTSUBMIT;
}
// Make sure we don't assign negative or too high marks
@@ -294,6 +294,9 @@ class question_match_qtype extends quiz_default_questiontype {
0.0), 1.0) * $question->maxgrade;
$state->penalty = $question->penalty * $question->maxgrade;
// mark the state as graded
$state->event = ($state->event == QUESTION_EVENTCLOSE) ? QUESTION_EVENTCLOSEANDGRADE : QUESTION_EVENTGRADE;
return true;
}
@@ -356,6 +356,9 @@ class quiz_embedded_cloze_qtype extends quiz_default_questiontype {
}
$state->penalty = $question->penalty * $question->maxgrade;
// mark the state as graded
$state->event = ($state->event == QUESTION_EVENTCLOSE) ? QUESTION_EVENTCLOSEANDGRADE : QUESTION_EVENTGRADE;
return true;
}
@@ -350,6 +350,9 @@ class question_multichoice_qtype extends quiz_default_questiontype {
// Apply the penalty for this attempt
$state->penalty = $question->penalty * $question->maxgrade;
// mark the state as graded
$state->event = ($state->event == QUESTION_EVENTCLOSE) ? QUESTION_EVENTCLOSEANDGRADE : QUESTION_EVENTGRADE;
return true;
}
@@ -292,6 +292,9 @@ class question_numerical_qtype extends question_shortanswer_qtype {
0.0), 1.0) * $question->maxgrade;
$state->penalty = $question->penalty * $question->maxgrade;
// mark the state as graded
$state->event = ($state->event == QUESTION_EVENTCLOSE) ? QUESTION_EVENTCLOSEANDGRADE : QUESTION_EVENTGRADE;
return true;
}
+10 -6
View File
@@ -458,7 +458,7 @@ class quiz_default_questiontype {
$grade = '';
if ($question->maxgrade and $options->scores) {
if ($cmoptions->optionflags & QUIZ_ADAPTIVE) {
$grade = (!($state->last_graded->event == QUESTION_EVENTGRADE)) ? '--/' : round($state->last_graded->grade, $cmoptions->decimalpoints).'/';
$grade = (!question_state_is_graded($state->last_graded)) ? '--/' : round($state->last_graded->grade, $cmoptions->decimalpoints).'/';
}
$grade .= $question->maxgrade;
}
@@ -470,7 +470,7 @@ class quiz_default_questiontype {
$states = get_records_select('question_states', "attempt = '$state->attempt' AND question = '$question->id' AND event > '0'", 'seq_number DESC');
} else {
// show only graded states
$states = get_records_select('question_states', "attempt = '$state->attempt' AND question = '$question->id' AND event = '".QUESTION_EVENTGRADE."'", 'seq_number DESC');
$states = get_records_select('question_states', "attempt = '$state->attempt' AND question = '$question->id' AND event IN (".QUESTION_EVENTGRADE.','.QUESTION_EVENTCLOSEANDGRADE.")", 'seq_number DESC');
}
if (count($states) > 1) {
$strreviewquestion = get_string('reviewresponse', 'quiz');
@@ -531,12 +531,12 @@ class quiz_default_questiontype {
attempt and displays the overall grade obtained counting all previous
responses (and penalties) */
if (QUESTION_EVENTDUPLICATEGRADE == $state->event) {
if (QUESTION_EVENTDUPLICATE == $state->event) {
echo ' ';
print_string('duplicateresponse', 'quiz');
}
if (!empty($question->maxgrade) && $options->scores) {
if ($state->last_graded->event == QUESTION_EVENTGRADE) {
if (question_state_is_graded($state->last_graded)) {
// Display the grading details from the last graded state
$grade->cur = round($state->last_graded->grade, $cmoptions->decimalpoints);
$grade->max = $question->maxgrade;
@@ -566,7 +566,7 @@ class quiz_default_questiontype {
}
// print info about new penalty
// penalty is relevant only if the answer is not correct and further attempts are possible
if (($state->last_graded->raw_grade < $question->maxgrade) and (QUESTION_EVENTCLOSE !== $state->event)) {
if (($state->last_graded->raw_grade < $question->maxgrade) and (QUESTION_EVENTCLOSEANDGRADE !== $state->event)) {
if ('' !== $state->last_graded->penalty && ((float)$state->last_graded->penalty) > 0.0) {
// A penalty was applied so display it
print_string('gradingdetailspenalty', 'quiz', $state->last_graded->penalty);
@@ -718,6 +718,7 @@ class quiz_default_questiontype {
// arrays. The ordering of the arrays does not matter.
// Question types may wish to override this (eg. to ignore trailing
// white space or to make "7.0" and "7" compare equal).
if ($question->qtype = MATCH) {var_dump($state->responses);echo '<br>Teststate:';var_dump($teststate->responses);}
return $state->responses == $teststate->responses;
}
@@ -750,7 +751,7 @@ class quiz_default_questiontype {
* must be updated. The method is able to
* close the question session (preventing any further
* attempts at this question) by setting
* $state->event to QUESTION_EVENTCLOSE.
* $state->event to QUESTION_EVENTCLOSEANDGRADE
* @param object $cmoptions
*/
function grade_responses(&$question, &$state, $cmoptions) {
@@ -776,6 +777,9 @@ class quiz_default_questiontype {
// Only allow one attempt at the question
$state->penalty = 1;
// mark the state as graded
$state->event = ($state->event == QUESTION_EVENTCLOSE) ? QUESTION_EVENTCLOSEANDGRADE : QUESTION_EVENTGRADE;
return true;
}
@@ -360,6 +360,7 @@ class question_rqp_qtype extends quiz_default_questiontype {
* This function calls RQP_Render to perform response processing and grading
* and updates the state accordingly. It also caches the rendering output in case
* it is needed later.
* TODO: set $state->event appropriately
* @return boolean Indicates success or failure.
* @param object $question The question to be graded.
* @param object $state The state of the question to grade. The current
@@ -198,6 +198,9 @@ class question_shortanswer_qtype extends quiz_default_questiontype {
0.0), 1.0) * $question->maxgrade;
$state->penalty = $question->penalty * $question->maxgrade;
// mark the state as graded
$state->event = ($state->event == QUESTION_EVENTCLOSE) ? QUESTION_EVENTCLOSEANDGRADE : QUESTION_EVENTGRADE;
return true;
}
@@ -194,6 +194,9 @@ class question_truefalse_qtype extends quiz_default_questiontype {
// Only allow one attempt at the question
$state->penalty = 1;
// mark the state as graded
$state->event = ($state->event == QUESTION_EVENTCLOSE) ? QUESTION_EVENTCLOSEANDGRADE : QUESTION_EVENTGRADE;
return true;
}