/* scantron control program for named surveys
   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.
*/

#include <stdio.h>
#include "Capa/capaCommon.h"
#include "bubbler.h"


#include <ctype.h>

#ifdef __sun
#include <unistd.h>  /* lockf() */
#endif

#include "capaParser.h"
#include "capaToken.h"
#include "ranlib.h"
/*********************************************/
/*  flock() in SUN is in BSD compatibility lib */
/*  #include <sys/file.h> */

#ifdef   F_DBUG
extern FILE *dfp; 
#endif


/********************************************************** file locking */
int
flockstream_sh(sp) FILE *sp;
{
  int fd;
  
  fd = fileno(sp);
  
#ifdef __sun
  return ( lockf(fd,F_LOCK, 0L) );
#else
  return (flock(fd,LOCK_SH));
#endif
}

int
flockstream(sp) FILE *sp;
{
  int fd;
  
  fd = fileno(sp);
  
#ifdef __sun
  return ( lockf(fd,F_LOCK, 0L) );
#else
  return (flock(fd,LOCK_EX));
#endif
}
int
funlockstream(sp) FILE *sp;
{
  int fd;
  
  fd = fileno(sp);
  
#ifdef __sun
  return ( lockf(fd,F_ULOCK, 0L) );
#else
  return (flock(fd,LOCK_UN));
#endif
}

char *
capa_malloc(num,sz) unsigned num,sz;
{
  char *p;
  p = calloc(num, sz);
  return (p);
}


/****************************************************** Database Entry */
int /* RETURNS: error code */
capa_set_entry(entry, student_number, set, offset) 
T_entry   *entry;          /* pointer to entry structure to fill in */
char      *student_number;
int        set;
long       offset;
{
   FILE    *fp;
   int      errcode=0;
   int      len;
   char     filename[FILE_NAME_LENGTH];
   char     a_line[512];

   sprintf(filename,"records/set%d.db",set);
   if ((fp=fopen(filename,"r+"))==NULL) {
      printf("Error: can't open %s\n",filename);  return (-1);
   }
   sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
   len = strlen(a_line);
   flockstream(fp);
   fseek(fp,offset,0);
     if (!fwrite(a_line,len,1,fp) ) {
       printf("Error writing data to file\n");
       errcode= (-1);
     }
   funlockstream(fp);
   fclose(fp);
   return (errcode);
}

/**************************************************** Get db entry*/

long /* RETURNS: byte offset to start of record, 0 if error,
                    -offset if not found & newly created  */
capa_get_entry(entry, student_number, set) 
T_entry   *entry;           
char      *student_number;  
int        set;            
{
   char      filename[FILE_NAME_LENGTH];
   FILE     *fp;
   int       len, nq;          
   char     *ans_p, *tries_p, oneline[512],fmtbuf[128];          
   long      offset, next_r;             
   int       ii, done=0, found=0;
   char      a_sn[MAX_STUDENT_NUMBER+1];
   
   sprintf(filename,"records/set%d.db",set); 
   if ((fp=fopen(filename,"r"))==NULL) {
      printf("Error: can't open %s\n",filename);
      return (-1); 
   }
   sprintf(entry->student_number,"%s",student_number);
   sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
   flockstream(fp);
   fgets(oneline,511,fp); len = strlen(oneline); sscanf(oneline,"%d",&nq);
   ans_p = capa_malloc(nq+1,1); tries_p = capa_malloc(3*nq,1);
   fgets(oneline,511,fp); /* skip weight line */
   fgets(oneline,511,fp); /* hand grading */
   done = 0;
   while(!done) {
     done = !fgets(oneline,511,fp); len = strlen(oneline);
     if( !done ) {
       sscanf(oneline,fmtbuf,a_sn);
       if( !strncasecmp(a_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
         next_r = ftell(fp); offset = next_r - len; done = 1; found = 1;
       }
     } else {
       fseek(fp,0L,SEEK_END);
       offset = ftell(fp);  /* last byte, if last bye is cr, back up one */
       fseek(fp,-1L,SEEK_END);
       while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
       offset = offset +2; /* last char and cr */
       found = 0; done=1;
     }
   }
   funlockstream(fp); fclose(fp);
   if(!found) {
     for(ii=0;ii<nq;ii++) { /* Initialize answer string and tries string */
       ans_p[ii] = '-'; tries_p[3*ii] = ' '; tries_p[3*ii + 1] = '0';
       if(ii < nq-1) tries_p[3*ii + 2] = ',';
     }
     entry->answers = ans_p;
     entry->tries   = tries_p;
     capa_set_entry(entry,student_number,set,offset);
     offset = -offset;
   } else {
     sprintf(fmtbuf, "%%%dc",nq);
     sscanf(oneline + MAX_STUDENT_NUMBER+1,fmtbuf,ans_p);
     sprintf(fmtbuf, "%%%dc",(3*nq-1));
     sscanf(oneline + MAX_STUDENT_NUMBER+1+nq+1,fmtbuf,tries_p);
     entry->answers = ans_p;
     entry->tries   = tries_p;
   }
   return (offset);
}

int main()
{
  T_entry grade,examgrade;
  FILE * inputFile, * outputFile;
  int i=0,setnumber,score,section,setId,done=0,numQuestions,examSetId;
  char class[10],set[3],name[MAX_NAME_CHAR+1],buf,buffmt[128],
      studentnumber[MAX_STUDENT_NUMBER+1],filename[128];
  int q=0,r=0,answerTop[MAXQUEST][11],answerMid[MAXQUEST][11],
      answerBot[MAXQUEST][11],examtotal=0,firstDiv,secondDiv;
  Question questions[MAXQUEST];
  
  printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
  printf("Covert form Bubbler output to survey results ");
  printf("Version 0.1.00\n");
  printf("Please enter the Set Id number. of survey");
  scanf("%d",&setId);
  printf("Please enter the SetId of the Final exam.");
  scanf("%d",&examSetId);
  printf("Please enter score of first divison.");
  scanf("%d",&firstDiv);
  printf("Please enter score of second divison.");
  scanf("%d",&secondDiv);
  sprintf(filename,"bubbler.output.%d",setId);
  inputFile=fopen(filename,"r");

  if (inputFile==NULL)
    {
      fprintf(stderr,"%s not found\n",filename);
      exit(-1);
    }

  fscanf(inputFile,"%s %s",class,set);
  printf("%s %s\n",class,set);
  setnumber=atoi(set);

  i=0;
  fscanf(inputFile,"%c",&buf);
  while(!done)
    {
      buf=fgetc(inputFile);
      if (buf!='\n')
	{
	  questions[i].type=buf;
	  buf=fgetc(inputFile);
	  questions[i].points=questions[i].leafs=(int)(buf-'0');
	  i++;
	}
      else
	{
	  done=1;
	}
    }
  
  numQuestions=i;

  for(q=0;q<MAXQUEST;q++)
    for(r=0;r<11;r++)
      {
	answerTop[q][r]=0;
	answerMid[q][r]=0;
	answerBot[q][r]=0;
      }

  printf("Processing");
  while(fscanf(inputFile,"%s",studentnumber)!=EOF)
    {
      examtotal=0;
      printf(".");
      fflush(stdout);
      fscanf(inputFile,"%32c",name);
      sprintf(buffmt,"%%%dc",numQuestions);
      fscanf(inputFile,buffmt,grade.answers);
      fscanf(inputFile,"%d",&score);
      fscanf(inputFile,"%d",&section);
      buf='\0';
      while(buf!='\n')
	{
	  buf=fgetc(inputFile);
	}
      capa_get_entry(&examgrade,studentnumber,examSetId);
      
#ifdef DEBUG
      printf("%d %d\n",numQuestions,strlen(grade.answers));
#endif /*DEBUG*/

      for(i=0;i<numQuestions;i++)
	{
	  switch(examgrade.answers[i])
	    {
	    case 'Y':
	    case 'y':
	      i=0;
	      fprintf(stderr,"Skipping %s b/c of Ys\n",studentnumber);
	      goto skip_student;
	      break;
	    case 'N':
	    case 'n':
	      i=0;
	      fprintf(stderr,"Skipping %s b/c of Ns\n",studentnumber);
	      goto skip_student;	      
	      break;
	    case ' ':
	    case '-':
	      i=0;
	      fprintf(stderr,"Skipping %s b/c not complete\n",studentnumber);
	      goto skip_student;
	      break;
	    default:
	      if (isdigit(examgrade.answers[i]))
		{
		  examtotal+=(int)(examgrade.answers[i]-'0');
		}
	      else
		{
		  i=0;
		  fprintf(stderr,"Skipping %s b/c weird\n",studentnumber);
		  goto skip_student;
		}
	      break;
	    }
	}
      for(i=0;i<numQuestions;i++)
	{
	  switch(questions[i].type)
	    {
	    case 'a':
	    case 'f':
	    case 'g':
	    case 'b':
	    case 'c':
	    case 'e':
	    case 'd':
	      if (isdigit(grade.answers[i]))
		{
		  if (examtotal < firstDiv)
		    answerBot[i][grade.answers[i]-'0']++;
		  else if (examtotal < secondDiv)
		    answerMid[i][grade.answers[i]-'0']++;
		  else
		    answerTop[i][grade.answers[i]-'0']++;
		}
	      else if(isspace(grade.answers[i]))
		{
		  if (examtotal < firstDiv)
		    answerBot[i][10]++;
		  else if (examtotal < secondDiv)
		    answerMid[i][10]++;
		  else
		    answerTop[i][10]++;
		}
	      break;
	    default:
	      printf("Unknown question type\n");
	      break;
	    }
	}
      skip_student:
      grade.answers[i]='\0';
#ifdef DEBUG
      printf("%s\n",studentnumber);
#endif /*DEBUG*/
    }

  sprintf(filename,"surveyexam.%d",setId);
  outputFile=fopen(filename,"w");
  if (outputFile==NULL)
    {
      fprintf(stderr,"%s not found\n",filename);
      exit(-1);
    }

  fprintf(outputFile,"Bottom Third:\n");
  for(q=0;q<numQuestions;q++)
    {
      fprintf(outputFile,"Question: %d\n",q+1);
      fprintf(outputFile,"  0   1   2   3   4   5   6   7   8   9   S\n");
      for(r=0;r<11;r++)
	{
	  fprintf(outputFile,"%3d ",answerBot[q][r]);
	}
      fprintf(outputFile,"\n");
    }
  fprintf(outputFile,"\014Middle Third:\n");
  for(q=0;q<numQuestions;q++)
    {
      fprintf(outputFile,"Question: %d\n",q+1);
      fprintf(outputFile,"  0   1   2   3   4   5   6   7   8   9   S\n");
      for(r=0;r<11;r++)
	{
	  fprintf(outputFile,"%3d ",answerMid[q][r]);
	}
      fprintf(outputFile,"\n");
    }
  fprintf(outputFile,"\014Top Third:\n");
  for(q=0;q<numQuestions;q++)
    {
      fprintf(outputFile,"Question: %d\n",q+1);
      fprintf(outputFile,"  0   1   2   3   4   5   6   7   8   9   S\n");
      for(r=0;r<11;r++)
	{
	  fprintf(outputFile,"%3d ",answerTop[q][r]);
	}
      fprintf(outputFile,"\n");
    }
  printf("\nProcessing completed. Look in survey.%d for results.\n",
	 setId);
  return 0;
}
