--- loncom/interface/lonquickgrades.pm 2011/05/24 18:06:10 1.90
+++ loncom/interface/lonquickgrades.pm 2011/06/03 00:04:47 1.99
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Quick Student Grades Display
#
-# $Id: lonquickgrades.pm,v 1.90 2011/05/24 18:06:10 www Exp $
+# $Id: lonquickgrades.pm,v 1.99 2011/06/03 00:04:47 www Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -125,11 +125,28 @@ sub real_handler {
$navmap,$totalParts,$totalPossible,$totalRight,$totalAttempted,$topLevelParts,$topLevelRight,$topLevelAttempted);
}
if ($cangrade) { $r->print("\n\n"); }
+
&endGradeScreen($r);
return OK;
}
+sub getStudentCatGrade {
+ my ($uname,$udom,%categories)=@_;
+ my ($navmap,$totalParts,$totalPossible,$totalRight,$totalAttempted,$topLevelParts,$topLevelRight,$topLevelAttempted)=
+ &getData(1,$uname,$udom);
+ return &output_category_table(undef,0,$navmap,0,%categories);
+}
+
+sub getAllStudentData {
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my %categories=&Apache::lonnet::dump('grading_categories',$cdom,$cnum);
+#FIXME: debugging output
+ return &getStudentCatGrade('korte','gerd',%categories);
+}
+
+
sub startGradeScreen {
my ($r,$mode)=@_;
@@ -242,39 +259,40 @@ sub getData {
my $stack = $iterator->getStack();
for my $part (@{$parts}) {
- my $completionStatus = $curRes->getCompletionStatus($part);
my $dateStatus = $curRes->getDateStatus($part);
-
- if ($completionStatus == $curRes->EXCUSED()) {
+ my $weight = $curRes->weight($part);
+ my $problemstatus = $curRes->problemstatus($part);
+
+ if ($curRes->solved($part) eq 'excused') {
next;
}
if ($showPoints) {
my $score = 0;
# If we're not telling status and the answer date isn't passed yet,
# it's an "attempted" point
- if ((($curRes->problemstatus($part) eq 'no') ||
- ($curRes->problemstatus($part) eq 'no_feedback_ever')) &&
+ if ((($problemstatus eq 'no') ||
+ ($problemstatus eq 'no_feedback_ever')) &&
($dateStatus != $curRes->ANSWER_OPEN)) {
my $status = $curRes->simpleStatus($part);
if ($status == $curRes->ATTEMPTED) {
- $partsAttempted += $curRes->weight($part);
+ $partsAttempted += $weight;
$totalAttempted += $partsAttempted;
}
} else {
- $score = &Apache::grades::compute_points($curRes->weight($part), $curRes->awarded($part));
+ $score = &Apache::grades::compute_points($weight, $curRes->awarded($part));
}
$partsRight += $score;
$totalRight += $score;
- $partsCount += $curRes->weight($part);
+ $partsCount += $weight;
$curRes->{DATA}->{PROB_SCORE} += $score;
- $curRes->{DATA}->{PROB_WEIGHT} += $curRes->weight($part);
+ $curRes->{DATA}->{PROB_WEIGHT} += $weight;
if ($curRes->opendate($part) < $now) {
- $totalPossible += $curRes->weight($part);
- $curRes->{DATA}->{PROB_POSSIBLE} += $curRes->weight($part);
+ $totalPossible += $weight;
+ $curRes->{DATA}->{PROB_POSSIBLE} += $weight;
}
- $totalParts += $curRes->weight($part);
+ $totalParts += $weight;
} else {
my $status = $curRes->simpleStatus($part);
my $thisright = 0;
@@ -291,7 +309,6 @@ sub getData {
$totalAttempted++;
}
- my $dateStatus = $curRes->getDateStatus($part);
$totalParts++;
if ($curRes->opendate($part) < $now) {
$totalPossible++;
@@ -461,7 +478,7 @@ sub outputCategories {
&Apache::lonnet::put('grading_categories',\%categories,$cdom,$cnum);
}
# new categories loaded now
- &output_category_table($r,$cangrade,$navmap,%categories);
+ &output_category_table($r,$cangrade,$navmap,1,%categories);
#
if ($cangrade) {
$r->print(&Apache::loncommon::resourcebrowser_javascript().
@@ -471,13 +488,6 @@ sub outputCategories {
''.
'');
}
-#
-# Debug
-#
-# my %data=&dumpdata($navmap);
-# foreach (keys(%data)) {
-# $r->print("\n ".$_.'='.$data{$_});
-# }
}
#
@@ -560,27 +570,36 @@ sub process_category_edits {
#
sub output_category_table {
- my ($r,$cangrade,$navmaps,%categories)=@_;
- my $sum=0;
- my $total=0;
- $r->print(&Apache::loncommon::start_data_table());
+ my ($r,$cangrade,$navmaps,$output,%categories)=@_;
+
+ my $totalweight=0;
+ my $totalpoints=0;
+
+ if ($output) {
+ $r->print(&Apache::loncommon::start_data_table());
#
- &output_category_table_header($r,$cangrade);
+ &output_category_table_header($r,$cangrade);
+ }
#
my @order=split(/\,/,$categories{'order'});
#
my %performance=&dumpdata($navmaps);
my $maxpos=$#order;
for (my $i=0;$i<=$maxpos;$i++) {
- my ($value,$weight)=&output_and_calc_category($r,$cangrade,$navmaps,$order[$i],$i,$maxpos,\%performance,1,%categories);
- $sum+=$value*$weight;
- $total+=$weight;
+ my ($correct,$possible,$type,$weight)=&output_and_calc_category($r,$cangrade,$navmaps,$order[$i],$i,$maxpos,\%performance,$output,%categories);
+ unless ($possible) { next; }
+ $totalpoints+=$weight*$correct/$possible;
+ $totalweight+=$weight;
}
#
- &bottom_line_category($r,$cangrade,$sum,$total);
-#
- $r->print(&Apache::loncommon::end_data_table());
- return $sum;
+ my $perc=0;
+ if ($totalweight) { $perc=100.*$totalpoints/$totalweight; }
+
+ if ($output) {
+ &bottom_line_category($r,$cangrade,$perc);
+ $r->print(&Apache::loncommon::end_data_table());
+ }
+ return $perc;
}
sub output_category_table_header {
@@ -605,15 +624,15 @@ sub output_category_table_header {
sub output_and_calc_category {
my ($r,$cangrade,$navmaps,$id,$currentpos,$maxpos,$performance,$output,%categories)=@_;
- my $value=0;
- my $weight=0;
- my $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL') . "/");
- my %lt=&Apache::lonlocal::texthash(
- 'up' => 'Move Up',
- 'dw' => 'Move Down');
+
if ($output) { $r->print("\n".&Apache::loncommon::start_data_table_row()); }
if ($output && $cangrade) {
+ my $iconpath = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL') . "/");
+ my %lt=&Apache::lonlocal::texthash(
+ 'up' => 'Move Up',
+ 'dw' => 'Move Down');
+
$r->print(<
@@ -646,14 +665,16 @@ ENDMOVE
# Content display and summing up of points
my $totalpossible=0;
my $totalcorrect=0;
+ my @individual=();
if ($output) { $r->print('
'); }
foreach my $contentid (split(/\,/,$categories{$id.'_content'})) {
my ($type,$possible,$attempted,$correct)=split(/\:/,$$performance{$contentid});
$totalpossible+=$possible;
$totalcorrect+=$correct;
+ if ($possible>0) { push(@individual,"$possible:$correct"); }
if ($output) {
$r->print('
'.&mt('Total raw points: [_1]/[_2]',$totalcorrect,$totalpossible).'
');
if ($cangrade) {
$r->print(' '.&Apache::loncommon::selectresource_link('quickform','addcont_'.$id,&mt('Add Problem or Folder')).' ');
}
+ $r->print('
'.&mt('Total raw points: [_1]/[_2]',&numberout($totalcorrect),&numberout($totalpossible)).'
');
$r->print('
');
}
# Total
@@ -690,7 +711,7 @@ ENDMOVE
$totalpossible=1.*$categories{$id.'_total'};
}
if ($output) {
- $r->print('
'.&mt('Adjusted raw points: [_1]/[_2]',$totalcorrect,$totalpossible).'
');
+ $r->print('
'.&mt('Adjusted raw points: [_1]/[_2]',&numberout($totalcorrect),&numberout($totalpossible)).'
');
}
@@ -703,62 +724,147 @@ ENDMOVE
if ($cangrade) {
if ($output) { $r->print(' '.&mt('Delete').''); }
}
+ if ($code eq 'capabove') {
+ if ($totalpossible>0) {
+ if ($totalcorrect/$totalpossible>$value/100.) {
+ $totalcorrect=$totalpossible*$value/100.;
+ }
+ }
+ } elsif ($code eq 'capbelow') {
+ if ($totalpossible>0) {
+ if ($totalcorrect/$totalpossible<$value/100.) {
+ $totalcorrect=$totalpossible*$value/100.;
+ }
+ }
+ } elsif ($code eq 'droplow') {
+ ($totalpossible,$totalcorrect,@individual)=&drop(0,0,$value,@individual);
+ } elsif ($code eq 'drophigh') {
+ ($totalpossible,$totalcorrect,@individual)=&drop(1,0,$value,@individual);
+ } elsif ($code eq 'droplowperc') {
+ ($totalpossible,$totalcorrect,@individual)=&drop(0,1,$value,@individual);
+ } elsif ($code eq 'drophighperc') {
+ ($totalpossible,$totalcorrect,@individual)=&drop(1,1,$value,@individual);
+ }
if ($output) { $r->print(''); }
}
- if ($output) { $r->print(''); }
- if ($cangrade) {
- if ($output) { $r->print(' '.&new_calc_rule_form($id)); }
+# Re-adjust total points if force total
+ if ($categories{$id.'_totaltype'} eq 'typein') {
+ $totalpossible=1.*$categories{$id.'_total'};
}
- if ($output) { $r->print(''); }
+ if ($output) {
+ $r->print('');
+ if ($cangrade) { $r->print(' '.&new_calc_rule_form($id)); }
+ $r->print('
'); }
if ($cangrade) {
if ($output) {
$r->print('');
}
- } else {
- if ($output) {
- if ($categories{$id.'_displayachieved'} eq 'percent') {
- $r->print(&mt('percent'));
- } else {
- $r->print(&mt('points'));
+ }
+ if ($output) {
+ $r->print('
');
+ if ($type eq 'percent') {
+ my $perc='---';
+ if ($totalpossible) {
+ $perc=100.*$totalcorrect/$totalpossible;
}
+ $r->print(&mt('[_1] percent',&numberout($perc)));
+ } else {
+ $r->print(&mt('[_1]/[_2] points',&numberout($totalcorrect),&numberout($totalpossible)));
}
+ $r->print('
');
}
if ($output) { $r->print('
'); }
- return ($value,$weight);
+ return ($totalcorrect,$totalpossible,$type,$weight);
}
#
+# Drop folders and problems
+#
+
+sub drop {
+ my ($high,$percent,$n,@individual)=@_;
+# Sort assignments by points or percent
+ my @newindividual=sort {
+ my ($pa,$ca)=split(/\:/,$a);
+ my ($pb,$cb)=split(/\:/,$b);
+ if ($percent) {
+ my $perca=0;
+ if ($pa>0) { $perca=$ca/$pa; }
+ my $percb=0;
+ if ($pb>0) { $percb=$cb/$pb; }
+ $perca<=>$percb;
+ } else {
+ $ca<=>$cb;
+ }
+ } @individual;
+# Drop the ones we don't want
+ if ($#newindividual>=$n) {
+ if ($high) {
+ splice(@newindividual,$#newindividual+1-$n,$n);
+ } else {
+ splice(@newindividual,0,$n);
+ }
+ } else {
+ @newindividual=();
+ }
+# Re-calculate how many points possible and achieved
+ my $newpossible=0;
+ my $newcorrect=0;
+ for my $score (@newindividual) {
+ my ($thispossible,$thiscorrect)=(split(/\:/,$score));
+ $newpossible+=$thispossible;
+ $newcorrect+=$thiscorrect;
+ }
+ return ($newpossible,$newcorrect,@newindividual);
+}
+#
# Bottom line with grades
#
sub bottom_line_category {
- my ($r,$cangrade,$sum,$total)=@_;
+ my ($r,$cangrade,$perc)=@_;
$r->print(&Apache::loncommon::start_data_table_row());
if ($cangrade) {
$r->print('