#!/usr/local/bin/perl #computes and prints histograms of class average numerals and Letters, output file #in grades/finalLetters.lst with SID Letter pairs #Letter grade outputs only if $final is set to 1 #If first parameter is not a number, assumed to be a search string using grep -i #will only compute values for THAT search string #If next parameter is numerical, it turns on printing of seas names for class average #histogram and if >5 sets width of # of names to print on a line require "/w/class.01/cs/cs131/cs131ta/risc/grades/column_names";#has column labels and indexes $final=0; #if true, computes/prints letter grades and output file $res=2; #resolution of histogram $names=shift @ARGV if ($ARGV[0] =~ m:^\d\d?$:); #width parameter for putting seas names #beside class averages distribution $names=5 if ($names && $names <5); %weights = ( hw1pa => .04, hw1wa => .01, hw2pa => .05, hw2wa => .01, hw3pa => .07, hw3wa => .01, hw4pa => .05, hw4wa => .01, hw5pa => .07, hw5wa => .01, hw6pa => .06, hw6wa => .01, mid => .3, final => .3, ); map {$sum+=$_} (values %weights); if ($sum!=1) { #check that weights sum to 1 print "Sum=$sum\n"; exit; } @letgrades=qw (A B+ B B- C+ C C- D+ D D- F); #spaces don't matter, just for visual @cutoffs =qw (90 85 80 74 72 70 68 63 60 55 0); #as long as indexing lines them up @keys=keys %weights; if (@ARGV) {#just those who match $names=5; $ARGV[0]=join ('|', @ARGV) if $#ARGV; @grades=`/usr/xpg4/bin/grep -i -E \"$ARGV[0]\" $grade_file`; @avgsline=split (/,/, `grep -i average $grade_file`); } else {#all students &readgrades; shift @grades; @avgsline=split (/,/, pop @grades, -1); } foreach $col (@keys) { #determine how many points possible so far if ($avgsline[$columns{$col}] =~ m:\d:) {$possible+=$weights{$col};} } foreach $student (@grades) { $current=0; @sgrades=split (/,/, $student, -1); foreach $col (@keys) { if ($sgrades[$columns{$col}]=~m:\b(\d+(.\d+)?)\b:) { $value=$1; $value*=50 if ($col =~ m:wa:); #wa graded out of 2 points, rest out of 100 $current+=$weights{$col}*$value; } } if ($final) { $letter=&getletter($current); $letters{$letter}++; push @avgs, "$sgrades[$columns{'sid'}] $letter\n"; push @{$letnames{$letter}}, $sgrades[$columns{'seas'}]; } if (@ARGV) {printf "%10s %-12s raw=%3.2f of %3.1f, avg=%3.2f%%\n", $sgrades[$columns{"fname"}], $sgrades[$columns{"lname"}], $current, 100*$possible, $current/$possible;} $overall+=$current; $count++ if $current>0; $scores{int $current/$res}++; push @scores, $current; push @{$names{int $current/$res}}, $sgrades[$columns{'seas'}]; } exit if @ARGV; printf "overall average for $count people is %.1f out of %.1f, which is %.1f%%\n", $overall/$count, 100*$possible, $overall/$count/$possible if $count>0; if ($names) { #find max width for alignment foreach $key (sort {$b <=> $a} keys %scores) {$width= $scores{$key} if ($scores{$key} >$width);} $width+=2; } $sofar=0; foreach $key (sort {$b <=> $a} keys %scores) { #sort decreasing $sofar+= 100*$scores{$key}/$count; printf (">= %2d %4.1f%% (%5.1f%%) %2d %-${width}s", $res*$key, 100*$scores{$key}/$count, $sofar, $scores{$key}, "x" x $scores{$key}); if ($names) { $i=1; while ( $names*$i < $#{$names{$key}}) { $names{$key}[$i++*$names-1].="\n " . ' ' x $width . '| '; } print "| @{$names{$key}}"; } print "\n"; } if ($final) { open (OUT, ">$home/grades/finalLetters.lst") or die "Can't create finalLetters.lst: $!\n"; print OUT @avgs; close OUT; print "\n"; foreach $key (@letgrades) { printf "%-2s: %4.1f%% %2d %-${width}s", $key, $letters{$key}/$count*100, $letters{$key}, 'x' x $letters{$key}; if ($names) {print " | ", join (' ', @{$letnames{$key}});} print "\n"; } } @scores=sort @scores; print "@scores\n"; sub getletter { #print "got $_[0], c2=$cutoffs[2], p=$possible, x=", $_[0]/$possible, "\n"; # for ($i=0; $i<@cutoffs; $i++) {if ($_[0] >= $cutoffs[$i]) {return $letgrades[$i];}} for ($i=0; $i<@cutoffs; $i++) {if ($_[0]/$possible >= $cutoffs[$i]) {return $letgrades[$i];}} }