Hi Gregg,
I wrote an incremental_grader which we used for a while and then
dropped in favor of just limiting the number of submissions allowed
for a problem. The idea is essentially what you've said: on the first
however many submissions full credit should be possible, and then after
some number the amount of credit one can get should decrease. We used
it to give full credit for up to four submissions, then drop to 70%,
50%, 30% or 10% on the next four, with no credit given after that. I
wrote it a while ago, so I won't swear that it's the most elegant way
of doing this, but I append it below for your information. I do think
it works, at least.
@penalty is actually the amount of credit that one can get on
each submission, @penPerc is the same thing but written as a percent
because I'm lazy and didn't bother to format the entries in @penalty
for printing out. Note that the values of @penPerc are explicitly
referenced in the body of the routine, so that if the length of the
array changed it would be necessary to also edit that. Also, I had this
in a macro file for the course, so all of the backslashes are
backslashes instead of double tildes.
I hope this is useful.
Cheers,
Gavin
sub incremental_grader {
# grader to give partial credit on subsequent attempts. all parts of # the problem must be correct to get credit; if this is done on the # attempt $n, $penalty[$n] credit is given.
# standard input my $rh_evaluated_answers = shift; my $rh_problem_state = shift; my %form_options = @_;
# the hash %$rh_evaluated_answers contains the answers supplied: # 'AnSwEr1' => 'supplied answer', 'AnSwEr2' => 'next answer', # etc. # the hash %$rh_problem_state is the current state of the problem.
# %form_options might include the user login name, the permission # level of the user, the studentLogin name for this psvn, # whether the form is asking for a refresh or is submitting # a new answer, etc.
# by default, return current problem state my %problem_state = %$rh_problem_state;
# penalty for subsequent submissions my @penalty = ( 1, 1, 1, 1, 0.7, 0.5, 0.3, 0.1, 0 ); my @penPerc = ( '100%', '100%', '100%', '100%', '70%', '50%', '30%', '10%' );
my %problem_result = # initialize result (score => 0, errors => '', type => 'incremental_grader', msg => "Credit for this problem decreases with " . "subsequent attempts: on the first four, $penPerc[0] " . "is possible; " . "after that, $penPerc[4], $penPerc[5], $penPerc[6]," . " and " . "$penPerc[7] may be earned.");
# if answers were submitted, figure out which were correct if ( $form_options{'answers_submitted'} ) { my $total = 0; foreach ( keys %$rh_evaluated_answers ) { $total += $$rh_evaluated_answers{$_}>{'score'} if ( defined($$rh_evaluated_answers{$_}>{'score'}) ); } my $numPossible = scalar(keys %$rh_evaluated_answers);
my $numTimes = $main::envir{'numOfAttempts'}  1; $numTimes = @penalty if ($numTimes > @penalty);
# update score for problem; check if the problem is already # correct, and if not update it accordingly my ($inCorrect, $correct, $probScore) = (0, 0, 0); $correct = $problem_state{'num_of_correct_ans'} if ( defined($problem_state{'num_of_correct_ans'}) ); $inCorrect = $problem_state{'num_of_incorrect_ans'} if ( defined($problem_state{'num_of_incorrect_ans'}) ); $probScore = $problem_state{'recorded_score'} if ( defined($problem_state{'recorded_score'}) );
if ( $total == $numPossible ) { $probScore = $penalty[$numTimes] if ( ! $correct ); $correct++; } else { $inCorrect++; }
# and we return... $problem_result{'score'} = $total/$numPossible; $problem_result{'errors'} = ''; $problem_result{'type'} = 'incremental_grader'; $problem_result{'msg'} = "Credit for this problem decreases" . " with " . "subsequent attempts: on the first four, $penPerc[0] is" . " possible; " . "after that, $penPerc[4], $penPerc[5], $penPerc[6], " . "and $penPerc[7] may be earned."; $problem_state{'recorded_score'} = $probScore; $problem_state{'num_of_correct_ans'} = $correct; $problem_state{'num_of_incorrect_ans'} = $inCorrect; } return ( %problem_result, %problem_state ); }
< Post or View Comments >
