#!/usr/local/bin/perl # # Jan 30 1997 by Isaac Tsai based on code written by Lily Cheng # some simple statistics for CAPA # Copyright (C) 1992-2000 Michigan State University # # The CAPA system 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. # # The CAPA system 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 the CAPA system; see the file COPYING. If not, # write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # As a special exception, you have permission to link this program # with the TtH/TtM library and distribute executables, as long as you # follow the requirements of the GNU GPL in regard to all of the # software in the executable aside from TtH/TtM. # require('getopts.pl'); $MAX_TRIES = 99; $Usage = "USAGE: capastat.pl [-s set][-t TryUpperLimit][-n NumberOfOccurrence]"; sub S_Enterpath { local($set)=@_; local($notdone,$path); local($cfullpath); $notdone = 1; while ($notdone) { print "Please enter the CLASS absolute path:\n"; $path = <>; chomp($path); if( $path =~ /\/$/ ) { $cfullpath = "$path" . "classl"; $Rfullpath = "$path" . "records"; $Sfullpath = "$path" . "records/set$set.db"; } else { $cfullpath = "$path" . "/classl"; $Rfullpath = "$path" . "/records"; $Sfullpath = "$path" . "/records/set$set.db"; } if( -d $path ) { if( -d $Rfullpath ) { if( -f $Sfullpath ) { $notdone = 0; } else { print "File [$Sfullpath] does not exist!\n"; } } else { print "Directory [$Rfullpath] does not exist!\n"; } } else { print "Directory [$path] does not exist!\n"; } } return ($path); } sub S_ScanDB { local($filename)=@_; local($line_cnt)=0; local($valid_cnt)=0; local($valid); local($ii); local($s_num,$ans_str,$rest); local(@ans_char,@tries); local($score); open(IN, "<$filename") || die "Cannot open $filename file!"; while () { $line_cnt++; if( $line_cnt == 2 ) { chomp(); (@Weight) = split(/ */); } if( $line_cnt > 3) { chomp(); ($s_num,$ans_str,$rest) = split(/ /,$_,3); chop($ans_str); # chop off one extr , (@ans_char) = split(/ */,$ans_str); (@tries) = split(/,/,$rest); for($valid = 'N', $ii=0;$ii<=$#ans_char;$ii++) { $valid = 'Y' if $ans_char[$ii] ne '-'; } if( $valid eq 'Y' ) { for($score=0,$ii=0;$ii<=$#tries;$ii++) { $Student_cnt[$ii][$tries[$ii]]++; $Student_try[$valid_cnt][$ii] = $tries[$ii]; $Total_try[$ii] += $tries[$ii]; $Total_weight += $Weight[$ii]; if($ans_char[$ii] eq 'Y') { $Yes_cnt[$ii]++; $score += $Weight[$ii]; } if($ans_char[$ii] eq 'y') { $yes_cnt[$ii]++; $score += $Weight[$ii]; } if( $ans_char[$ii] >= 0 && $ans_char[$ii] <= 9) { $score += $ans_char[$ii]; } } $Total_scores += $score; $Entry{"$valid_cnt"} = "$s_num\n" . "$ans_str," . " $rest\n"; $Score{"$valid_cnt"} = $score; $valid_cnt++; } } } close(IN) || die "Cannot close $filename file!"; return ($#tries+1,$valid_cnt); } sub S_Average { local($q_cnt,$l_cnt)=@_; local($ii,$jj); local(@s_cnt,@avg); local(@sd, $sum); local($sq); local(@sd3,$tmp1,$tmp2); for($ii=0;$ii<$q_cnt;$ii++) { $s_cnt[$ii] = 0; $avg[$ii] = 0.0; for($jj=1;$jj<$MAX_TRIES;$jj++) { # ignore the 0 try entry if( $Student_cnt[$ii][$jj] > 0 ) { $avg[$ii] += $jj*$Student_cnt[$ii][$jj]; $s_cnt[$ii] += $Student_cnt[$ii][$jj]; } } if( $s_cnt[$ii] > 0 ) { # avoid division by zero $avg[$ii] = $avg[$ii] / $s_cnt[$ii]; } } for($ii=0;$ii<$q_cnt;$ii++) { $sd[$ii] = 0.0; $sum = 0.0; for($jj=0;$jj<$l_cnt;$jj++) { $Max_try[$ii] = ($Student_try[$jj][$ii] > $Max_try[$ii]? $Student_try[$jj][$ii] : $Max_try[$ii]); if( $Student_try[$jj][$ii] > 0 ) { $sq = ($Student_try[$jj][$ii] - $avg[$ii])*($Student_try[$jj][$ii] - $avg[$ii]); $sum += $sq; } if( $s_cnt[$ii] > 1 ) { $sd[$ii] = $sum / ($s_cnt[$ii] - 1.0 ); } if( $sd[$ii] > 0 ) { $sd[$ii] = sqrt( $sd[$ii] ); } } } for($ii=0;$ii<$q_cnt;$ii++) { $sd3[$ii] = 0.0; $sum = 0.0; for($jj=0;$jj<$l_cnt;$jj++) { if( $Student_try[$jj][$ii] > 0 ) { $tmp1 = $Student_try[$jj][$ii] - $avg[$ii]; $tmp2 = $tmp1*$tmp1*$tmp1; $sum = $sum + $tmp2; } if( $s_cnt[$ii] > 0 && $sd[$ii] != 0.0 ) { $sd3[$ii] = $sum/$s_cnt[$ii] ; $sd3[$ii] = $sd3[$ii] / ($sd[$ii]*$sd[$ii]*$sd[$ii]); } } } print "\nThis is the statistics for each problem:\n"; print "Prob\# MxTries avg. s.d. s.k. \#Stdnts "; print " \#Yes \#yes Tries DoDiff\n"; for($ii=0;$ii<$q_cnt;$ii++) { if( $Total_try[$ii] > 0 ) { $dod = 1-($Yes_cnt[$ii] + $yes_cnt[$ii]) / $Total_try[$ii]; } printf "P %2d:",$ii+1; printf "%7d %8.2f %7.2f %6.2f %5d %5d %5d %5d %5.2f\n", $Max_try[$ii],$avg[$ii],$sd[$ii],$sd3[$ii],$s_cnt[$ii],$Yes_cnt[$ii],$yes_cnt[$ii], $Total_try[$ii],$dod; } } sub Percentage_Scores { local($set)=@_; local($ratio); if($Total_weight > 0 ) { $ratio = $Total_scores / $Total_weight; $ratio = $ratio * 100.0; } printf "\nThe percentage score for set%d.db is %7.2f%%\n",$set,$ratio; } sub Large_Tries { local($t,$n,$q_cnt,$l_cnt)=@_; local($ii); print "\nHere is a list of students who attempts $t tries more than $n times: \n\n"; for ($i=0;$i<$l_cnt;$i++){ $count=0; $credit=0; for ($j=0;$j<$q_cnt;$j++){ if ($Student_try[$i][$j]>= $t){ $count++; } } if ($count >= $n){ print "($Score{$i}) $Entry{$i} \n"; } } } if(! &Getopts('s:t:n:') ) { print STDERR "$Usage\n"; exit 2; } $opt_s = 1 if ! $opt_s; $opt_t = 99 if ! $opt_t; $opt_n = 1 if ! $opt_n; S_Enterpath($opt_s); ($Q_cnt,$L_cnt) = S_ScanDB("$Sfullpath"); Percentage_Scores($opt_s); S_Average($Q_cnt,$L_cnt); Large_Tries($opt_t,$opt_n,$Q_cnt,$L_cnt);