--- loncom/homework/grades.pm 2003/06/20 21:45:20 1.105
+++ loncom/homework/grades.pm 2003/07/25 20:35:40 1.125
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.105 2003/06/20 21:45:20 albertel Exp $
+# $Id: grades.pm,v 1.125 2003/07/25 20:35:40 ng Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -33,6 +33,7 @@
# June-August H.K. Ng
# Year 2003
# February, March H.K. Ng
+# July, H. K. Ng
#
package Apache::grades;
@@ -41,6 +42,7 @@ use Apache::style;
use Apache::lonxml;
use Apache::lonnet;
use Apache::loncommon;
+use Apache::lonhtmlcommon;
use Apache::lonnavmaps;
use Apache::lonhomework;
use Apache::loncoursedata;
@@ -97,7 +99,8 @@ sub get_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 ($url,$symb) = shift;
+ $symb=($ENV{'form.symb'} ne '' ? $ENV{'form.symb'} : (&Apache::lonnet::symbread($url))) if ($symb eq '');
my $allkeys = &Apache::lonnet::metadata($url,'keys');
my %seen = ();
my (@partlist,%handgrade);
@@ -105,7 +108,10 @@ sub response_type {
if (/^\w+response_\w+.*/) {
my ($responsetype,$part) = split(/_/,$_,2);
my ($partid,$respid) = split(/_/,$part);
- $handgrade{$part} = $responsetype.':'.($allkeys =~ /parameter_$part\_handgrade/ ? 'yes' : 'no');
+ $responsetype =~ s/response$//; # make it compatible w/ navmaps - should move to that!!
+# my ($value) = &Apache::lonnet::EXT('resource.'.$part.'.handgrade',$symb);
+# $handgrade{$part} = $responsetype.':'.($value eq 'yes' ? 'yes' : 'no'); #a bug $value is 'yes' regardless
+ $handgrade{$part} = $responsetype.':'.(($allkeys =~ /parameter_$part\_handgrade/) ? 'yes' : 'no');
next if ($seen{$partid} > 0);
$seen{$partid}++;
push @partlist,$partid;
@@ -114,10 +120,105 @@ sub response_type {
return \@partlist,\%handgrade;
}
+#--- Show resource title
+#--- and parts and response type
+sub showResourceInfo {
+ my ($url,$probTitle) = @_;
+ my $result ='
'.
+ '
Current Resource: '.$probTitle.'
'."\n";
+ my ($partlist,$handgrade) = &response_type($url);
+ my %resptype = (); #,$hdgrade)=('','no');
+ my $hdgrade='no';
+ for (sort keys(%$handgrade)) {
+ my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_});
+ my $partID = (split(/_/))[0];
+ $resptype{$partID} = $responsetype;
+ $hdgrade = $handgrade if ($handgrade eq 'yes');
+ $result.='
Part '.$partID.'
'.
+ '
Type: '.$responsetype.'
';
+# '
Handgrade: '.$handgrade.'
';
+ }
+ $result.='
'."\n";
+ return $result,\%resptype,$hdgrade,$partlist,$handgrade;
+}
+
+#--- Clean response type for display
+#--- Currently filters option response type only.
+sub cleanRecord {
+ my ($answer,$response,$symb) = @_;
+ if ($response eq 'option') {
+ my (@IDs,@ans);
+ foreach (split(/\&/,&Apache::lonnet::unescape($answer))) {
+ my ($optionID,$ans) = split(/=/);
+ push @IDs,$optionID.'';
+ push @ans,$ans;
+ }
+ my $grayFont = '';
+ return '
'.
+ '
Answer
'.
+ (join '
',@ans).'
'.
+ '
'.$grayFont.'Option ID
'.$grayFont.
+ (join '
'.$grayFont,@IDs).'
'.
+ '
';
+ }
+ if ($response eq 'essay') {
+ if (! exists ($ENV{'form.'.$symb})) {
+ my (%keyhash) = &Apache::lonnet::dump('nohist_handgrade',
+ $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
+ $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+
+ my $loginuser = $ENV{'user.name'}.':'.$ENV{'user.domain'};
+ $ENV{'form.keywords'} = $keyhash{$symb.'_keywords'} ne '' ? $keyhash{$symb.'_keywords'} : '';
+ $ENV{'form.kwclr'} = $keyhash{$loginuser.'_kwclr'} ne '' ? $keyhash{$loginuser.'_kwclr'} : 'red';
+ $ENV{'form.kwsize'} = $keyhash{$loginuser.'_kwsize'} ne '' ? $keyhash{$loginuser.'_kwsize'} : '0';
+ $ENV{'form.kwstyle'} = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : '';
+ $ENV{'form.'.$symb} = 1; # so that we don't have to read it from disk for multiple sub of the same prob.
+ }
+ return &keywords_highlight($answer);
+ }
+ return $answer;
+}
+
+#-- A couple of common js functions
+sub commonJSfunctions {
+ my $request = shift;
+ $request->print(<
+ function radioSelection(radioButton) {
+ var selection=null;
+ if (radioButton.length > 1) {
+ for (var i=0; i 1) {
+ for (var i=0; i
+COMMONJSFUNCTIONS
+}
+
#--- Dumps the class list with usernames,list of sections,
#--- section, ids and fullnames for each user.
sub getclasslist {
my ($getsec,$filterlist) = @_;
+ $getsec = $getsec eq '' ? 'all' : $getsec;
my $classlist=&Apache::loncoursedata::get_classlist();
# Bail out if we were unable to get the classlist
return if (! defined($classlist));
@@ -129,14 +230,14 @@ sub getclasslist {
my (undef,undef,$end,$start,$id,$section,$fullname,$status)=
@{$classlist->{$_}};
# filter students according to status selected
- if ($filterlist && $ENV{'form.status'} ne 'Any') {
- if ($ENV{'form.status'} ne $status) {
+ if ($filterlist && $ENV{'form.Status'} ne 'Any') {
+ if ($ENV{'form.Status'} ne $status) {
delete ($classlist->{$_});
next;
}
}
$section = ($section ne '' ? $section : 'no');
- if (1 || &canview($section)) {
+ if (&canview($section)) {
if ($getsec eq 'all' || $getsec eq $section) {
$sections{$section}++;
$fullnames{$_}=$fullname;
@@ -224,6 +325,7 @@ sub jscriptNform {
''."\n".
''."\n".
''."\n".
+ ''."\n".
''."\n".
''."\n".
''."\n".
@@ -296,7 +398,7 @@ sub verifyreceipt {
my $title.='
'.
- $viewgrade.
- ' Submissions for a Student or a Group of Students
'.
- '
'.
- 'Problem: '.$ENV{'form.probTitle'}.'
'.$result;
+ my $result='
'.$viewgrade.
+ ' Submissions for a Student or a Group of Students
';
+
+ my ($table,undef,$hdgrade,$partlist,$handgrade) = &showResourceInfo($url,$ENV{'form.probTitle'});
+ $result.=$table;
$request->print(<
- function checkSelect(checkBox) {
- var ctr=0;
- var sense="";
- if (checkBox.length > 1) {
- for (var i=0; i 1) {
+ for (var i=0; i
LISTJAVASCRIPT
+ &commonJSfunctions($request);
$request->print($result);
- my $checkhdgrade = $ENV{'form.handgrade'} eq 'yes' ? 'checked' : '';
- my $checklastsub = $ENV{'form.handgrade'} eq 'yes' ? '' : 'checked';
-
+ my $checkhdgrade = ($ENV{'form.handgrade'} eq 'yes' && scalar(@$partlist) > 1 ) ? 'checked' : '';
+ my $checklastsub = $checkhdgrade eq '' ? 'checked' : '';
my $gradeTable='
'."\n";
- $studentTable.=' '."\n";
$studentTable.=&show_grading_menu_form($symb,$url);
@@ -2601,53 +2800,22 @@ LISTJAVASCRIPT
sub getSymbMap {
my ($request) = @_;
my $navmap = Apache::lonnavmaps::navmap-> new($ENV{'request.course.fn'}.'.db',
- $ENV{'request.course.fn'}.'_parms.db',1, 1);
-
- my $res = $navmap->firstResource(); # temp resource to access constants
+ $ENV{'request.course.fn'}.'_parms.db');
$navmap->init();
- # End navmap using boilerplate
-
- my $iterator = $navmap->getIterator(undef, undef, undef, 1);
- my $depth = 1;
- $iterator->next(); # ignore first BEGIN_MAP
- my $curRes = $iterator->next();
-
my %symbx = ();
my @titles = ();
- my $minder=0;
- while ($depth > 0) {
- if ($curRes == $iterator->BEGIN_MAP()) {$depth++;}
- if ($curRes == $iterator->END_MAP()) { $depth--; }
+ my $minder = 0;
- if (ref($curRes) && $curRes->is_map()) {
- my ($mapUrl, $id, $resUrl) = split(/___/, $curRes->symb()); # check map contains at least one problem
- my $map = $navmap->getResourceByUrl($resUrl); # add to navmaps
-
- my $mapiterator = $navmap->getIterator($map->map_start(),
- $map->map_finish());
-
- my $mapdepth = 1;
- my $countProblems = 0;
- $mapiterator->next(); # skip the first BEGIN_MAP
- my $mapcurRes = $mapiterator->next(); # for "current resource"
- while ($mapdepth > 0) {
- if($mapcurRes == $mapiterator->BEGIN_MAP) { $mapdepth++; }
- if($mapcurRes == $mapiterator->END_MAP) { $mapdepth--; }
-
- if (ref($mapcurRes) && $mapcurRes->is_problem() && !$mapcurRes->randomout) {
- $countProblems++;
- }
- $mapcurRes = $mapiterator->next();
- }
- if ($countProblems > 0) {
- my $title = $curRes->compTitle();
- push @titles,$minder.'.'.$title; # minder, just in case two titles are identical
- $symbx{$minder.'.'.$title} = $curRes->symb();
- $minder++;
- }
- }
- $curRes = $iterator->next();
+ # Gather every sequence that has problems.
+ my @sequences = $navmap->retrieveResources(undef, sub { shift->is_map(); }, 1);
+ for my $sequence ($navmap->getById('0.0'), @sequences) {
+ if ($navmap->hasResource($sequence, sub { shift->is_problem(); }, 0) ) {
+ my $title = $minder.'.'.$sequence->compTitle();
+ push @titles, $title; # minder in case two titles are identical
+ $symbx{$title} = $sequence->symb();
+ $minder++;
+ }
}
$navmap->untieHashes();
@@ -2689,22 +2857,24 @@ sub displayPage {
my $studentTable='
'."\n".
''."\n".
+ ''."\n".
''."\n".
''."\n".
''."\n".
''."\n".
''."\n".
+ ''."\n".
''."\n";
my $checkIcon = '';
- $studentTable.=' Note: A problem graded correct ('.$checkIcon.
- ') by the computer cannot be changed.'."\n".
+ $studentTable.=' Note: Problems graded correct by the computer are marked with a '.$checkIcon.
+ ' symbol.'."\n".
'
|g;
$studentTable.=' '.$title.' Correct answer: '.$companswer;
}
@@ -2742,40 +2911,11 @@ sub displayPage {
if ($record{'version'} eq '') {
$studentTable.=' No recorded submission for this problem ';
} else {
- $studentTable.='
'.
- '
'.
- '
Date/Time
'.
- '
Submission
'.
- '
Status
';
- my ($version);
- for ($version=1;$version<=$record{'version'};$version++) {
- my $timestamp = scalar(localtime($record{$version.':timestamp'}));
- $studentTable.='
'."\n";
$request->print($result);
@@ -2840,7 +3021,7 @@ sub updateGradeByPage {
my $studentTable='
'.
'
'.
- '
No
'.
+ '
Prob.
'.
'
Title
'.
'
Previous Score
'.
'
New Score
';
@@ -2872,31 +3053,40 @@ sub updateGradeByPage {
my $score;
if ($partial > 0) {
$score = 'correct_by_override';
- } elsif ($partial == 0) {
+ } elsif ($newpts ne '') { #empty is taken as 0
$score = 'incorrect_by_override';
}
- if ($ENV{'form.GD_SEL'.$question.'_'.$partid} eq 'excused') {
+ my $dropMenu = $ENV{'form.GD_SEL'.$question.'_'.$partid};
+ if ($dropMenu eq 'excused') {
$partial = '';
$score = 'excused';
+ } elsif ($dropMenu eq 'reset status'
+ && $ENV{'form.solved'.$question.'_'.$partid} ne '') { #update only if previous record exists
+ print "got to reset = $ENV{'form.solved'.$question.'_'.$partid}: ";
+ $newrecord{'resource.'.$partid.'.tries'} = 0;
+ $newrecord{'resource.'.$partid.'.solved'} = '';
+ $newrecord{'resource.'.$partid.'.award'} = '';
+ $newrecord{'resource.'.$partid.'.awarded'} = 0;
+ $newrecord{'resource.'.$partid.'.regrader'} = "$ENV{'user.name'}:$ENV{'user.domain'}";
+ $changeflag++;
+ $newpts = '';
}
+
my $oldstatus = $ENV{'form.solved'.$question.'_'.$partid};
$displayPts[0].=' Part '.$partid.' = '.
(($oldstatus eq 'excused') ? 'excused' : $oldpts).
' ';
$displayPts[1].=' Part '.$partid.' = '.
- ($oldstatus eq 'correct_by_student' ? $oldpts :
- (($score eq 'excused') ? 'excused' : $newpts)).
+ (($score eq 'excused') ? 'excused' : $newpts).
' ';
$question++;
- if (($oldstatus eq 'correct_by_student') ||
- ($newpts eq $oldpts && $score eq $oldstatus))
- {
- next;
- }
+ next if ($dropMenu eq 'reset status' || ($newpts == $oldpts && $score ne 'excused'));
+
$newrecord{'resource.'.$partid.'.awarded'} = $partial if $partial ne '';
- $newrecord{'resource.'.$partid.'.solved'} = $score;
- $newrecord{'resource.'.$partid.'.regrader'}="$ENV{'user.name'}:$ENV{'user.domain'}";
+ $newrecord{'resource.'.$partid.'.solved'} = $score if $score ne '';
+ $newrecord{'resource.'.$partid.'.regrader'} = "$ENV{'user.name'}:$ENV{'user.domain'}"
+ if (scalar(keys(%newrecord)) > 0);
$changeflag++;
}
@@ -2904,6 +3094,7 @@ sub updateGradeByPage {
&Apache::lonnet::cstore(\%newrecord,$symbx,$ENV{'request.course.id'},
$udom,$uname);
}
+
$studentTable.='
'.$displayPts[0].'
'.
'
'.$displayPts[1].'
'.
'';
@@ -3245,7 +3436,7 @@ SCANTRONFORM
#--- Show a Grading Menu button - Calls the next routine ---
sub show_grading_menu_form {
my ($symb,$url)=@_;
- my $result.='
'."\n".
+ my $result.='
'."\n".
''."\n".
''."\n".
''."\n".
@@ -3276,12 +3467,19 @@ sub gradingmenu {
$request->print(<
- function checkChoice(formname) {
- var cmd = formname.command;
- formname.saveState.value = "saveCmd="+radioSelection(cmd)+":saveSec="+pullDownSelection(formname.section)+
- ":saveSub="+radioSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.status);
- if (cmd[0].checked || cmd[1].checked || cmd[2].checked || cmd[3].checked || cmd[4].checked) formname.submit();
- if (cmd[5].checked) {
+ function checkChoice(formname,val,cmdx) {
+ if (val <= 2) {
+ var cmd = radioSelection(formname.radioChoice);
+ var cmdsave = cmd;
+ } else {
+ cmd = cmdx;
+ cmdsave = 'submission';
+ }
+ formname.command.value = cmd;
+ formname.saveState.value = "saveCmd="+cmdsave+":saveSec="+pullDownSelection(formname.section)+
+ ":saveSub="+radioSelection(formname.submitonly)+":saveStatus="+pullDownSelection(formname.Status);
+ if (val < 5) formname.submit();
+ if (val == 5) {
if (!checkReceiptNo(formname,'notOK')) { return false;}
formname.submit();
}
@@ -3298,142 +3496,96 @@ sub gradingmenu {
formname.receipt.focus();
return false;
}
- formname.command[5].checked = true;
return true;
}
-
- function radioSelection(radioButton) {
- var selection=null;
- if (radioButton.length > 1) {
- for (var i=0; i 1) {
- for (var i=0; i
GRADINGMENUJS
-
- my $result='