--- loncom/homework/grades.pm 2001/02/09 03:24:45 1.2 +++ loncom/homework/grades.pm 2002/08/26 12:47:28 1.47 @@ -1,87 +1,2328 @@ +# The LearningOnline Network with CAPA # The LON-CAPA Grading handler -# Guy Albertelli -# 11/30 Gerd Kortemeyer -# 6/1 Gerd Kortemeyer +# +# $Id: grades.pm,v 1.47 2002/08/26 12:47:28 www Exp $ +# +# Copyright Michigan State University Board of Trustees +# +# This file is part of the LearningOnline Network with CAPA (LON-CAPA). +# +# LON-CAPA is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# LON-CAPA is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with LON-CAPA; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# /home/httpd/html/adm/gpl.txt +# +# http://www.lon-capa.org/ +# +# 2/9,2/13 Guy Albertelli +# 6/8 Gerd Kortemeyer +# 7/26 H.K. Ng +# 8/20 Gerd Kortemeyer +# Year 2002 +# June-August H.K. Ng +# package Apache::grades; use strict; use Apache::style; use Apache::lonxml; use Apache::lonnet; +use Apache::loncommon; use Apache::lonhomework; +use Apache::lonmsg qw(:user_normal_msg); use Apache::Constants qw(:common); -sub moreinfo { - my ($request,$reason) = @_; - $request->print("Unable to process request: $reason"); - $request->print('
'); +# ----- These first few routines are general use routines.----- +# +# --- Retrieve the parts that matches stores_\d+ from the metadata file.--- +sub getpartlist { + my ($url) = @_; + my @parts =(); + my (@metakeys) = split(/,/,&Apache::lonnet::metadata($url,'keys')); + foreach my $key (@metakeys) { + if ( $key =~ m/stores_([0-9]+)_.*/) { + push(@parts,$key); + } + } + return @parts; +} + +# --- Get the symbolic name of a problem and the url +sub get_symb_and_url { + my ($request) = @_; + (my $url=$ENV{'form.url'}) =~ s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--; + my $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url))); + if ($symb eq '') { $request->print("Unable to handle ambiguous references:$url:."); return ''; } + return ($symb,$url); +} + +# --- Retrieve the fullname for a user. Return lastname, first middle --- +# --- Generation is attached next to the lastname if it exists. --- +sub get_fullname { + my ($uname,$udom) = @_; + my %name=&Apache::lonnet::get('environment', ['lastname','generation', + 'firstname','middlename'],$udom,$uname); + my $fullname; + my ($tmp) = keys(%name); + if ($tmp !~ /^(con_lost|error|no_such_host)/i) { + $fullname=$name{'lastname'}.$name{'generation'}; + if ($fullname =~ /[^\s]+/) { $fullname.=', '; } + $fullname.=$name{'firstname'}.' '.$name{'middlename'}; + } + return $fullname; +} + +#--- Get the partlist and the response type for a given problem. --- +#--- Indicate if a response type is coded handgraded or not. --- +sub response_type { + my ($url) = shift; + my $allkeys = &Apache::lonnet::metadata($url,'keys'); + my %seen = (); + my (@partlist,%handgrade); + foreach (split(/,/,&Apache::lonnet::metadata($url,'packages'))) { + if (/^\w+response_\d+.*/) { + my ($responsetype,$part) = split(/_/,$_,2); + my ($partid,$respid) = split(/_/,$part); + $handgrade{$part} = $responsetype.':'.($allkeys =~ /parameter_$part\_handgrade/ ? 'yes' : 'no'); + next if ($seen{$partid} > 0); + $seen{$partid}++; + push @partlist,$partid; + } + } + return \@partlist,\%handgrade; } +#--- Dumps the class list with usernames,list of sections, +#--- section, ids and fullnames for each user. +sub getclasslist { + my ($getsec,$hideexpired) = @_; + my $now = time; + my %classlist=&Apache::lonnet::dump('classlist', + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); + # codes to check for fields in the classlist + # should contain end:start:id:section:fullname + for (keys %classlist) { + my (@fields) = split(/:/,$classlist{$_}); + %classlist = &reformat_classlist(\%classlist) if (scalar(@fields) <= 2); + last; + } + + my (@holdsec,@sections,%allids,%stusec,%fullname); + foreach (keys(%classlist)) { + my ($end,$start,$id,$section,$fullname)=split(/:/,$classlist{$_}); + # still a student? + if (($hideexpired) && ($end) && ($end < $now)) { + next; + } + $section = ($section ne '' ? $section : 'no'); + push @holdsec,$section; + if ($getsec eq 'all' || $getsec eq $section) { + push (@{ $classlist{$getsec} }, $_); + $allids{$_} =$id; + $stusec{$_} =$section; + $fullname{$_}=$fullname; + } + } + my %seen = (); + foreach my $item (@holdsec) { + push (@sections, $item) unless $seen{$item}++; + } + return (\%classlist,\@sections,\%allids,\%stusec,\%fullname); +} +# add id, section and fullname to the classlist.db +# done to maintain backward compatibility with older versions +sub reformat_classlist { + my ($classlist) = shift; + foreach (sort keys(%$classlist)) { + my ($unam,$udom) = split(/:/); + my $section = &Apache::lonnet::usection($udom,$unam,$ENV{'request.course.id'}); + my $fullname = &get_fullname ($unam,$udom); + my %userid = &Apache::lonnet::idrget($udom,($unam)); + $$classlist{$_} = $$classlist{$_}.':'.$userid{$unam}.':'.$section.':'.$fullname; + } + my $putresult = &Apache::lonnet::put + ('classlist',\%$classlist, + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); + + return %$classlist; +} + +#find user domain sub finduser { - my ($name) = @_; - + my ($name) = @_; + my $domain = ''; + if ( $Apache::grades::viewgrades eq 'F' ) { + my %classlist=&Apache::lonnet::dump('classlist', + $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, + $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); + my (@fields) = grep /^$name:/, keys %classlist; + ($name, $domain) = split(/:/,$fields[0]); + return ($name,$domain); + } else { + return ($ENV{'user.name'},$ENV{'user.domain'}); + } } -sub submission { - my ($request) = @_; - if ($ENV{'form.student'} eq '') { &moreinfo($request,"Need student login id"); return ''; } - my ($uname,$udom) = &finduser($ENV{'form.student'}); - if ($uname eq '') { &moreinfo($request,"Unable to find student"); return ''; } -# my $answer=&Apache::lonnet::reply( -# "restore:$udom:$uname:". -# $ENV{'request.course.id'}.':'. -# &Apache::lonnet::escape($symb), -# &Apache::lonnet::homeserver($uname,$udom)); - return ''; +#--- Prompts a user to enter a username. +sub moreinfo { + my ($request,$reason) = @_; + $request->print("Unable to process request: $reason"); + if ( $Apache::grades::viewgrades eq 'F' ) { + $request->print(''); + } + return ''; } -sub send_header { - my ($request)= @_; - $request->print(&Apache::lontexconvert::header()); - $request->print(''); +#--- Retrieve the grade status of a student for all the parts +sub student_gradeStatus { + my ($url,$symb,$udom,$uname,$partlist) = @_; + my %record = &Apache::lonnet::restore($symb,$ENV{'request.course.id'},$udom,$uname); + my %partstatus = (); + foreach (@$partlist) { + my ($status,$foo) = split(/_/,$record{"resource.$_.solved"},2); + $status = 'nothing' if ($status eq ''); + $partstatus{$_} = $status; + my $subkey = "resource.$_.submitted_by"; + $partstatus{$subkey} = $record{$subkey} if ($record{$subkey} ne ''); + } + return %partstatus; } -sub send_footer { - my ($request)= @_; - $request->print(''); - $request->print(&Apache::lontexconvert::footer()); +# hidden form and javascript that calls the form +# Use by verifyscript and viewgrades +# Shows a student's view of problem and submission +sub jscriptNform { + my ($url,$symb) = @_; + my $jscript=''."\n"; + $jscript.= ''."\n"; + return $jscript; } -sub handler { - my $request=$_[0]; +#------------------ End of general use routines -------------------- +#------------------------------------------------------------------- - if ( $ENV{'user.name'} eq 'albertel' ) {$Apache::lonxml::debug=1;} else {$Apache::lonxml::debug=0;} - - if ($ENV{'browser.mathml'}) { - $request->content_type('text/xml'); - } else { - $request->content_type('text/html'); - } - $request->send_http_header; - return OK if $request->header_only; - my $url=$ENV{'form.url'}; - my $command=$ENV{'form.command'}; - - &send_header($request); - if ($url eq '') { - $request->print("Non-Contextual Access Unsupported:$command:$url:"); - } else { - $Apache::grades::viewgrades=&Apache::lonnet::allowed('vgr',$url); - if ($command eq 'submission') { - &submission($request); +#------------------------------------ Receipt Verification Routines +# +#--- Check whether a receipt number is valid.--- +sub verifyreceipt { + my $request = shift; + + my $courseid = $ENV{'request.course.id'}; + my $receipt = unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}).'-'. + $ENV{'form.receipt'}; + $receipt =~ s/[^\-\d]//g; + my $url = $ENV{'form.url'}; + my $symb = $ENV{'form.symb'}; + unless ($symb) { + $symb = &Apache::lonnet::symbread($url); + } + + my $title.=''."\n".
+ '
|
'. + 'Resource: '.$ENV{'form.url'}.' | ||
Part '.(split(/_/))[0].' | '. + 'Type: '.$responsetype.' | '. + 'Handgrade: '.$handgrade.' |
';
+ $result.='
|
Part '.$partid.' Points: | ';
+
+ my $ctr = 0;
+ $result.='
| or | '; + $result.=''."\n"; + $result.=' | /'.$wgt.' '.$wgtmsg.' | '; + + $result.=''."\n". + ''. + ''."  \n"; + $result.=''; + $result.=' |
'. + ''."\n"; + if ($ENV{'form.handgrade'} eq 'yes') { + $endform.=' '."\n"; + my $ntstu =''."\n"; + my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1'); + $ntstu =~ s/ |
'."\n";
+ $result.= '
|
Resource: '.$url.' | ||
Part '.(split(/_/))[0].' | '. + 'Type: '.$responsetype.' | '. + 'Handgrade: '.$handgrade.' |
Resource: '.$url.' | ||
Part '.(split(/_/))[0].' | '. + 'Type: '.$responsetype.' | '. + 'Handgrade: '.$handgrade.' |
'."\n";
+ $result.='
|
'."\n";
+ $result.='
|
'."\n";
+ $result.='
|
'."\n";
+ $result.='
|