WeBWorK Main Forum

Deleted data

Deleted data

by Bruce Yoshiwara -
Number of replies: 5
My colleague who is sharing a WeBWorK class with me has mistakenly deleted one of my students. Is there any chance of recovering the student's data? (I had never made a WeBWorK report because I planned to wait until the end of the semester.)
In reply to Bruce Yoshiwara

Re: Deleted data

by Jason Aubrey -
Hi Bruce,

It might be painful, but you should be able to reconstruct the student's scores from answer_log. A typical entry looks like

[Wed Oct 07 18:50:04 2009] |malxvc|Exam_1_Problems|5|111110 1254959404 $1178.43 156 144 $125858.00 $119362.10 $6495.90

The "111110" indicates that this student correctly answered 5 of the 6 parts of this problem. So, if you extract all of your student's entries in answer_log, and then take the latest entry for each problem of each assignment, then you can figure out his scores on each of the homework assignments.

There might be an easier way. (e.g. you could ask your colleague to do this!)

Hope this helps,

In reply to Jason Aubrey

Re: Deleted data

by Bruce Yoshiwara -
Thanks. It doesn't look fun, but I'm glad to know the data are still recorded.
In reply to Bruce Yoshiwara

Re: Deleted data

by Bruce Yoshiwara -
Well, the student decided (with my subtle encouragement)that we base his entire WeBWorK average on what he achieves from now on. (So I won't need to resurrect his scores after all.)
In reply to Bruce Yoshiwara

Re: Deleted data

by Arnold Pizer -

I never tried this and I don't know of anybody who has but the following might work (but it probably wouldn't be worth the effort for one student). On an old spare computer make a clone of your webwork system. Then from your sysadmin get a system backup from a time just before the student was deleted. From that extract the mysql webwork database (i.e. the webwork directory) which is probably in a location similar to /var/lib/mysql/webwork . Then replace the mysql webwork database on the cloned system with the one from the system backup. Fire the cloned system up and hope for the best. You can then score the closed sets (or just look at the student's scores) and it would be fast to just record those. For the sets that were open you will be able to see what the student had done.

In reply to Arnold Pizer

Re: Deleted data

by Gavin LaRose -
Hi all,

For what it's worth, I just ended up doing much of what Bruce asked about on account of a small typo in a mysql command. My verdict is that it isn't hard to reconstruct student scores from the answer_log. I used a simple Perl script to suck in the answer_log and generate a mysql command file that reset the answers for the course, which I append below. Note that the logging for gateway/quiz assignments is slightly different than that for homeworks; in my system all gateway/quiz assignments are named with a "GW" at the end of the set_id, which motivates the conditional about the set_id ending with "GW. " I also name all of my classes "maCCC-SSS-tYY" (CCC-SSS is the course-section number, and tYY the term).

Note that this script assumes that the sets all still exist and the scores were just changed; e.g., if a student were deleted from the course and then added back in with all of the same set assignments.

One other note: this obviously sets the scores for all students in the course. Add the appropriate user_id conditional in the while loop to restrict to one or more users. Oh, and the script assumes that it's being run in the logfiles directory for the course.

#----script follows
#!/usr/bin/perl -w
use strict;

# use: ./alog2sql logfile_name > sqlfile_name

my $wd = `pwd`;

my $cl = $wd;
$cl =~ s/\/logs$//;
$cl =~ s/.*(ma\d\d\d.+)/$1/;
die(" * unable to determine class\n") if ( ! $cl );

my $update = 'update `' . $cl . '_problem_user` set status=SCORE where ' .
    'user_id=\'USER\' and set_id=\'SET\' and problem_id=PROBLEM;' . "\n";

while (  ) {
    my @fields = split( /\|/ );
    my $user_id = $fields[1];
    my $set_id  = $fields[2];
    my $prob_id = $fields[3];
    my $scorestring = $fields[4];

    if ( $set_id !~ /GW/ || 
         ( $set_id =~ /GW/ && $scorestring =~ /\[submit\]/ ) ) {
        my ( $right, @timeans ) = split( /\t/, $scorestring );
        my @parts = split(//, $right);
        my $score = 0;
        foreach my $s ( @parts ) { $score += $s; };
        $score = sprintf("%7.6f", $score/scalar(@parts));
        $score =~ s/0+$//;

        my $tmpcmd = $update;
        $tmpcmd =~ s/SCORE/$score/;
        $tmpcmd =~ s/USER/$user_id/;
        $tmpcmd =~ s/SET/$set_id/;
        $tmpcmd =~ s/PROBLEM/$prob_id/;

        print $tmpcmd;
#----end script