'.
'';
@@ -1346,6 +1352,15 @@ sub gradeBox {
my $result=''."\n";
my $display_part=&get_display_part($partid,undef,$symb);
+ my @partids = ("$partid");
+ my %last_resets = ();
+ &get_last_resets($symb,$env{'request.course.id'},\%last_resets,\@partids);
+ my $aggtries;
+ if ($last_resets{$partid}) {
+ $aggtries = &get_num_tries($record,$last_resets{$partid},$partid);
+ } else {
+ $aggtries = $$record{'resource.'.$partid.'.tries'};
+ }
$result.=''.
'Part: '.$display_part.' Points: | '."\n";
@@ -1384,7 +1399,11 @@ sub gradeBox {
$result.=''."\n".
''."\n".
''."\n";
+ $$record{'resource.'.$partid.'.solved'}.'" />'."\n".
+ ''."\n".
+ ''."\n";
$result.=' | '."\n";
return $result;
}
@@ -1593,7 +1612,6 @@ KEYWORDS
}
my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$udom,$uname);
-
my ($partlist,$handgrade,$responseType) = &response_type($url,$symb);
# Display student info
@@ -2109,6 +2127,7 @@ sub processHandGrade {
#---- Save the score and award for each student, if changed
sub saveHandGrade {
my ($request,$url,$symb,$stuname,$domain,$newflg,$submitter,$part) = @_;
+ my @v_flag;
my $usec = &Apache::lonnet::getsection($domain,$stuname,
$env{'request.course.id'});
if (!&canmodify($usec)) { return('not_allowed'); }
@@ -2116,45 +2135,62 @@ sub saveHandGrade {
my @parts_graded;
my %newrecord = ();
my ($pts,$wgt) = ('','');
- foreach (split(/:/,$env{'form.partlist'.$newflg})) {
+ my %aggregate = ();
+ my $aggregateflag = 0;
+ foreach my $new_part (split(/:/,$env{'form.partlist'.$newflg})) {
#collaborator may vary for different parts
- if ($submitter && $_ ne $part) { next; }
- my $dropMenu = $env{'form.GD_SEL'.$newflg.'_'.$_};
+ if ($submitter && $new_part ne $part) { next; }
+ my $dropMenu = $env{'form.GD_SEL'.$newflg.'_'.$new_part};
if ($dropMenu eq 'excused') {
- if ($record{'resource.'.$_.'.solved'} ne 'excused') {
- $newrecord{'resource.'.$_.'.solved'} = 'excused';
- if (exists($record{'resource.'.$_.'.awarded'})) {
- $newrecord{'resource.'.$_.'.awarded'} = '';
+ if ($record{'resource.'.$new_part.'.solved'} ne 'excused') {
+ $newrecord{'resource.'.$new_part.'.solved'} = 'excused';
+ if (exists($record{'resource.'.$new_part.'.awarded'})) {
+ $newrecord{'resource.'.$new_part.'.awarded'} = '';
}
- $newrecord{'resource.'.$_.'.regrader'}="$env{'user.name'}:$env{'user.domain'}";
+ $newrecord{'resource.'.$new_part.'.regrader'}="$env{'user.name'}:$env{'user.domain'}";
}
} elsif ($dropMenu eq 'reset status'
- && exists($record{'resource.'.$_.'.solved'})) { #don't bother if no old records -> no attempts
+ && exists($record{'resource.'.$new_part.'.solved'})) { #don't bother if no old records -> no attempts
foreach my $key (keys (%record)) {
- if ($key=~/^resource\.\Q$_\E\./) { $newrecord{$key} = ''; }
+ if ($key=~/^resource\.\Q$new_part\E\./) { $newrecord{$key} = ''; }
}
- $newrecord{'resource.'.$_.'.regrader'}=
+ $newrecord{'resource.'.$new_part.'.regrader'}=
"$env{'user.name'}:$env{'user.domain'}";
+ my @partids = ("$new_part");
+ my %last_resets = ();
+ &get_last_resets($symb,$env{'request.course.id'},\%last_resets,\@partids);
+ my ($totaltries,$aggtries,$solvedstatus);
+ $totaltries = $record{'resource.'.$part.'.tries'};
+ if ($last_resets{$new_part}) {
+ $aggtries = &get_num_tries(\%record,$last_resets{$new_part},$new_part);
+ } else {
+ $aggtries = $totaltries;
+ }
+ $solvedstatus = $record{'resource.'.$new_part.'.solved'};
+ if ($aggtries > 0) {
+ &decrement($symb,$new_part,\%aggregate,$aggtries,$totaltries,$solvedstatus);
+ $aggregateflag = 1;
+ }
} elsif ($dropMenu eq '') {
- $pts = ($env{'form.GD_BOX'.$newflg.'_'.$_} ne '' ?
- $env{'form.GD_BOX'.$newflg.'_'.$_} :
- $env{'form.RADVAL'.$newflg.'_'.$_});
- if ($pts eq '' && $env{'form.GD_SEL'.$newflg.'_'.$_} eq '') {
+ $pts = ($env{'form.GD_BOX'.$newflg.'_'.$new_part} ne '' ?
+ $env{'form.GD_BOX'.$newflg.'_'.$new_part} :
+ $env{'form.RADVAL'.$newflg.'_'.$new_part});
+ if ($pts eq '' && $env{'form.GD_SEL'.$newflg.'_'.$new_part} eq '') {
next;
}
- $wgt = $env{'form.WGT'.$newflg.'_'.$_} eq '' ? 1 :
- $env{'form.WGT'.$newflg.'_'.$_};
+ $wgt = $env{'form.WGT'.$newflg.'_'.$new_part} eq '' ? 1 :
+ $env{'form.WGT'.$newflg.'_'.$new_part};
my $partial= $pts/$wgt;
- if ($partial eq $record{'resource.'.$_.'.awarded'}) {
+ if ($partial eq $record{'resource.'.$new_part.'.awarded'}) {
#do not update score for part if not changed.
next;
} else {
- push @parts_graded, $_;
+ push @parts_graded, $new_part;
}
- if ($record{'resource.'.$_.'.awarded'} ne $partial) {
- $newrecord{'resource.'.$_.'.awarded'} = $partial;
+ if ($record{'resource.'.$new_part.'.awarded'} ne $partial) {
+ $newrecord{'resource.'.$new_part.'.awarded'} = $partial;
}
- my $reckey = 'resource.'.$_.'.solved';
+ my $reckey = 'resource.'.$new_part.'.solved';
if ($partial == 0) {
if ($record{$reckey} ne 'incorrect_by_override') {
$newrecord{$reckey} = 'incorrect_by_override';
@@ -2165,32 +2201,109 @@ sub saveHandGrade {
}
}
if ($submitter &&
- ($record{'resource.'.$_.'.submitted_by'} ne $submitter)) {
- $newrecord{'resource.'.$_.'.submitted_by'} = $submitter;
+ ($record{'resource.'.$new_part.'.submitted_by'} ne $submitter)) {
+ $newrecord{'resource.'.$new_part.'.submitted_by'} = $submitter;
}
- $newrecord{'resource.'.$_.'.regrader'}=
+ $newrecord{'resource.'.$new_part.'.regrader'}=
"$env{'user.name'}:$env{'user.domain'}";
}
+ # unless problem has been graded, set flag to version the submitted files
+ unless ($record{'resource.'.$new_part.'.solved'} =~ /^correct_/ || $record{'resource.'.$new_part.'.solved'} eq 'incorrect_by_override') {
+ push (@v_flag,$new_part);
+ }
}
if (scalar(keys(%newrecord)) > 0) {
- &version_portfiles(\%record, \@parts_graded, $env{'request.course.id'}, $symb, $domain, $stuname);
+ if (scalar(@v_flag)) {
+ &version_portfiles(\%record, \@parts_graded, $env{'request.course.id'}, $symb, $domain, $stuname, \@v_flag);
+ }
&Apache::lonnet::cstore(\%newrecord,$symb,
$env{'request.course.id'},$domain,$stuname);
}
+ if ($aggregateflag) {
+ &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate,
+ $env{'course.'.$env{'request.course.id'}.'.domain'},
+ $env{'course.'.$env{'request.course.id'}.'.num'});
+ }
return '',$pts,$wgt;
}
+# ----------- Provides number of tries since last reset.
+sub get_num_tries {
+ my ($record,$last_reset,$part) = @_;
+ my $timestamp = '';
+ my $num_tries = 0;
+ if ($$record{'version'}) {
+ for (my $version=$$record{'version'};$version>=1;$version--) {
+ if (exists($$record{$version.':resource.'.$part.'.solved'})) {
+ $timestamp = $$record{$version.':timestamp'};
+ if ($timestamp > $last_reset) {
+ $num_tries ++;
+ } else {
+ last;
+ }
+ }
+ }
+ }
+ return $num_tries;
+}
+
+# ----------- Determine decrements required in aggregate totals
+sub decrement_aggs {
+ my ($symb,$part,$aggregate,$aggtries,$totaltries,$solvedstatus) = @_;
+ my %decrement = (
+ attempts => 0,
+ users => 0,
+ correct => 0
+ );
+ $decrement{'attempts'} = $aggtries;
+ if ($solvedstatus =~ /^correct/) {
+ $decrement{'correct'} = 1;
+ }
+ if ($aggtries == $totaltries) {
+ $decrement{'users'} = 1;
+ }
+ foreach my $type (keys (%decrement)) {
+ $$aggregate{$symb."\0".$part."\0".$type} = -$decrement{$type};
+ }
+ return;
+}
+
+# ----------- Determine timestamps for last reset of aggregate totals for parts
+sub get_last_resets {
+ my ($symb,$courseid,$last_resets,$partids) =@_;
+ my $cdom = $env{'course.'.$courseid.'.domain'};
+ my $cname = $env{'course.'.$courseid.'.num'};
+ my %resethash = &Apache::lonnet::restore($symb,'nohist_resourcetracker',$cdom,$cname);
+ if ($resethash{'version'}) {
+ foreach my $part (@{$partids}) {
+ $$last_resets{$part} = '';
+ for (my $version=$resethash{'version'};$version>=1;$version--) {
+ if (exists($resethash{$version.':'.$part."\0".'prev_attempts'})) {
+ $$last_resets{$part} = $resethash{$version.':timestamp'};
+ last;
+ }
+ }
+ }
+ }
+ return;
+}
+
# ----------- Handles creating versions for portfolio files as answers
sub version_portfiles {
- my ($record, $parts_graded, $courseid, $symb, $domain, $stuname) = @_;
+ my ($record, $parts_graded, $courseid, $symb, $domain, $stuname, $v_flag) = @_;
+ my $version_parts = join('|',@$v_flag);
my $parts = join('|', @$parts_graded);
my $portfolio_root = &Apache::loncommon::propath($domain,
$stuname).
'/userfiles/portfolio';
foreach my $key(keys %$record) {
- if ($key =~ /^resource\.($parts)\./ && $key =~ /\.portfiles$/) {
+ my $new_portfiles;
+ if ($key =~ /^resource\.($version_parts)\./ && $key =~ /\.portfiles$/ ) {
+ my @v_portfiles;
my @portfiles = split(/,/,$$record{$key});
+ # &Apache::lonnet::logthis("should be unmarking and remarking");
foreach my $file (@portfiles) {
+ &Apache::lonnet::unmark_as_readonly($domain,$stuname,[$symb,$env{'request.course.id'}],$file);
my ($directory,$answer_file) =($file =~ /^(.*?)([^\/]*$)/);
my $version = 0;
my @answer_file_parts = split(/\./, $answer_file);
@@ -2212,20 +2325,22 @@ sub version_portfiles {
}
$version++;
my $home_server = &Apache::lonnet::homeserver($stuname,$domain,undef);
- $ENV{'form.copy'} = &Apache::lonnet::getfile("/uploaded/$domain/$stuname/$directory$answer_file");
- # $ENV{'form.copy.filename'}='';
- my $copy_result = &Apache::lonnet::finishuserfileupload($stuname,$domain,$home_server,'copy',
+ $env{'form.copy'} = &Apache::lonnet::getfile("/uploaded/$domain/$stuname/portfolio$directory$answer_file");
+ if($env{'form.copy'} eq '-1') {
+ &Apache::lonnet::logthis('problem getting file '.$directory.$answer_file);
+ } else {
+ my $copy_result = &Apache::lonnet::finishuserfileupload($stuname,$domain,$home_server,'copy',
'/portfolio'.$directory.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]);
- &Apache::lonnet::logthis('copy result is '.$copy_result);
- &Apache::lonnet::logthis('answer file is '.$answer_file.
- ' becomes '.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]);
- &Apache::lonnet::logthis('from dir list is '.$file_names[0].' has '.@file_name_parts.' parts');
+ push(@v_portfiles, $answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]);
+ &Apache::lonnet::mark_as_readonly($domain,$stuname,
+ ['/portfolio'.$directory.$answer_file_parts[0].'.'.$version.'.'.$answer_file_parts[-1]],
+ [$symb,$env{'request.course.id'},'graded']);
+ }
}
- &Apache::lonnet::logthis('found key portfiles '.$key);
- &Apache::lonnet::logthis('found value portfiles '.$$record{$key});
+ $$record{$key} = join(',',@v_portfiles);
}
}
-
+ return 'ok';
}
@@ -2294,6 +2409,7 @@ sub viewgrades_js {
function writeRadText(partid,weight) {
var selval = document.classgrade["SELVAL_"+partid];
var radioButton = document.classgrade["RADVAL_"+partid];
+ var override = document.classgrade["FORCE_"+partid].checked;
var textbox = document.classgrade["TEXTVAL_"+partid];
if (selval[1].selected || selval[2].selected) {
for (var i=0; i '.
''.
''.
- ' '."\n";
+ ''.
+ ' | '."\n";
$ctsparts++;
}
$result.=' '.' |