#!/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 (<IN>) {
      $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);
  
  
  
