File:  [LON-CAPA] / capa / capa51 / Historic / bubbler.c
Revision 1.3: download - view: text, annotated - select for diffs
Mon Aug 7 20:47:29 2000 UTC (23 years, 10 months ago) by albertel
Branches: MAIN
CVS tags: version_2_9_X, version_2_9_99_0, version_2_9_1, version_2_9_0, version_2_8_X, version_2_8_99_1, version_2_8_99_0, version_2_8_2, version_2_8_1, version_2_8_0, version_2_7_X, version_2_7_99_1, version_2_7_99_0, version_2_7_1, version_2_7_0, version_2_6_X, version_2_6_99_1, version_2_6_99_0, version_2_6_3, version_2_6_2, version_2_6_1, version_2_6_0, version_2_5_X, version_2_5_99_1, version_2_5_99_0, version_2_5_2, version_2_5_1, version_2_5_0, version_2_4_X, version_2_4_99_0, version_2_4_2, version_2_4_1, version_2_4_0, version_2_3_X, version_2_3_99_0, version_2_3_2, version_2_3_1, version_2_3_0, version_2_2_X, version_2_2_99_1, version_2_2_99_0, version_2_2_2, version_2_2_1, version_2_2_0, version_2_1_X, version_2_1_99_3, version_2_1_99_2, version_2_1_99_1, version_2_1_99_0, version_2_1_3, version_2_1_2, version_2_1_1, version_2_1_0, version_2_12_X, version_2_11_X, version_2_11_4_uiuc, version_2_11_4_msu, version_2_11_4, version_2_11_3_uiuc, version_2_11_3_msu, version_2_11_3, version_2_11_2_uiuc, version_2_11_2_msu, version_2_11_2_educog, version_2_11_2, version_2_11_1, version_2_11_0_RC3, version_2_11_0_RC2, version_2_11_0_RC1, version_2_11_0, version_2_10_X, version_2_10_1, version_2_10_0_RC2, version_2_10_0_RC1, version_2_10_0, version_2_0_X, version_2_0_99_1, version_2_0_2, version_2_0_1, version_2_0_0, version_1_99_3, version_1_99_2, version_1_99_1_tmcc, version_1_99_1, version_1_99_0_tmcc, version_1_99_0, version_1_3_X, version_1_3_3, version_1_3_2, version_1_3_1, version_1_3_0, version_1_2_X, version_1_2_99_1, version_1_2_99_0, version_1_2_1, version_1_2_0, version_1_1_X, version_1_1_99_5, version_1_1_99_4, version_1_1_99_3, version_1_1_99_2, version_1_1_99_1, version_1_1_99_0, version_1_1_3, version_1_1_2, version_1_1_1, version_1_1_0, version_1_0_99_3, version_1_0_99_2, version_1_0_99_1, version_1_0_99, version_1_0_3, version_1_0_2, version_1_0_1, version_1_0_0, version_0_99_5, version_0_99_4, version_0_99_3, version_0_99_2, version_0_99_1, version_0_99_0, version_0_6_2, version_0_6, version_0_5_1, version_0_5, version_0_4, stable_2002_spring, stable_2002_july, stable_2002_april, stable_2001_fall, release_5-1-3, loncapaMITrelate_1, language_hyphenation_merge, language_hyphenation, conference_2003, bz6209-base, bz6209, STABLE, HEAD, GCI_3, GCI_2, GCI_1, CAPA_5-1-6, CAPA_5-1-5, CAPA_5-1-4_RC1, BZ4492-merge, BZ4492-feature_horizontal_radioresponse, BZ4492-feature_Support_horizontal_radioresponse, BZ4492-Support_horizontal_radioresponse
- fixed license notices the reference the GNU GPL rather than the GNU LGPL

#include <stdio.h>
#include <sgtty.h>
#include <libc.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <ctype.h>
#include "Capa/capaCommon.h"
#include "bubbler.h"
/* scantron control program
   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.
*/

int serportfd;
int readportfd;
FILE * readport;
int CheckPIN;
int CompareClassName;
int Anon;
int CheckSpaces;
int SurveyMode;
int SurveyHeader;
int formNumber;

int GetProblems(Question questions[MAXQUEST],char * class,int * setId)
{
  int i,q,length;
  char clear[100];

  printf("What is the class name?");
  scanf("%s",class);
  
  printf("What is the SetId?");
  scanf("%d",setId);

  printf("Is this a survey or exam/quiz?(s or e)");
  scanf("%s",clear);
  if (clear[0]=='s' || clear[0]=='S')
    {
      SurveyMode=1;
      printf("Does the form include a Header?(y or n)");
      scanf("%s",clear);
      if (clear[0]=='n' || clear[0]=='N')
	{
	  SurveyHeader=0;
	}
      else
	{
	  SurveyHeader=1;
	}
      printf("How many Questions are on the form?");
      scanf("%d",&q);
      
      for (i=0;i<q;i++)
	{
	  questions[i].type='d';
	  questions[i].leafs=questions[i].points=9;
	}
    }
  else
    {
      SurveyMode=0;

      printf("Should bubbler compare the entered class name and SetId with \n");
      printf("the encoded information on each paper?(y or n)");
      scanf("%s",clear);
      if (clear[0]=='N' || clear[0]=='n')
	CompareClassName=0;
      else
	CompareClassName=1;
      
      printf("Should the student coded CAPA ID be checked for correctness?\n");
      printf("(y or n)");
      scanf("%s",clear);
      if (clear[0]=='N' || clear[0]=='n')
	CheckPIN=0;
      else
	{
	  CheckPIN=1;
	  
	  printf("Should bubbler run in Anonymous mode (search for correct \n");
	  printf("Student Number based on the CAPA ID)? (y or n)");
	  scanf("%s",clear);
	  
	  if (clear[0]=='N' || clear[0]=='n')
	    Anon=0;
	  else
	    Anon=1;
	}
      
      printf("Should bubbler check for blank answers and issue a warning when \n");
      printf("one is encountered? (y or n)");
      scanf("%s",clear);
      if (clear[0]=='N' || clear[0]=='n')
	CheckSpaces=0;
      else
	CheckSpaces=1;
      
      length=strlen(class);
      if (length < 8)
	{
	  for(;length<8;length++)
	    {
	      class[length]=' ';
	    }
	  class[length]='\0';
	}
      printf("How many Questions are on the form?");
      scanf("%d",&q);
      
      printf("For Each Question enter \"a\" for a one out of 8\n");
      printf("                        \"b\" for a GLE type\n");
      printf("                        \"c\" for a TF type.\n");
      printf("                        \"d\" for an assigned score.\n");
      printf("                        \"e\" for a multiple out of 8.\n");
      printf("                        \"f\" for single digit string matching.\n");
      printf("                        \"g\" for exact string matching/\n");
      
      for (i=0;i<q;i++)
	{
	  printf("Question#%2d: ",i+1);
	  scanf("%1s",&questions[i].type);
	  fflush(stdin);
	  switch(questions[i].type)
	    {
	    case 'a':
	    case 'd':
	    case 'g':
	    case 'f':
	      printf("How many Points are possible?");
	      scanf("%d",&questions[i].points);
	      questions[i].leafs=questions[i].points;
	      break;
	    case 'b':
	    case 'c':
	      printf("How many parts to the problem?");
	      scanf("%d",&questions[i].points);
	      questions[i].leafs=questions[i].points;
	      break;
	    case 'e':
	      printf("How many possible answers are there?");
	      scanf("%d",&questions[i].points);
	      questions[i].leafs=questions[i].points;
	      break;
	    default:
	      printf("Unknown choice.\n");
	      break;
	    }
	  fflush(stdin);
	}
    }
  return q;
}
 
void serial_open(FILE ** streamserport,char * device)
{
  struct sgttyb one;
  
  if ((serportfd=open(device,O_WRONLY,O_CREAT))==-1)
    {
      fprintf(stderr,"Unable to open serial port.\n");
      exit(-1);
    }

  if ((readportfd=open(device,O_RDONLY,O_CREAT))==-1)
    {
      fprintf(stderr,"Unable to open serial port for reading.\n");
      exit(-1);
    }
  
  one.sg_ispeed='\015';
  one.sg_ospeed='\015';
  one.sg_erase='\177';
  one.sg_kill='\024';
  one.sg_flags= (short) 3;

#ifdef DEBUG  
  ioctl(serportfd,TIOCGETP,&two);
  printf("%d %d %d %d %d\n",two.sg_ispeed,two.sg_ospeed,
	 two.sg_erase,two.sg_kill,two.sg_flags);
#endif
  
  ioctl(serportfd,TIOCSETN,&one);
  ioctl(readportfd,TIOCSETN,&one);

#ifdef DEBUG
  ioctl(serportfd,TIOCGETP,&two);
  printf("%d %d %d %d %d\n",two.sg_ispeed,two.sg_ospeed,
	 two.sg_erase,two.sg_kill,two.sg_flags);
  printf("%d %d %d %d %d\n",one.sg_ispeed,one.sg_ospeed,
	 one.sg_erase,one.sg_kill,one.sg_flags);
#endif
  *streamserport=fdopen(serportfd,"w");
  readport=fdopen(readportfd,"r");
}


void print(FILE** serport,char * out,int shouldread)
{
  int readamount;
  char buf[100];

#ifdef DEBUG
  printf("%s\n",out);
#endif /*DEBUG*/

  write(serportfd,out,strlen(out));
  if (shouldread)
    {
      readamount=read(readportfd,buf,1);
#ifdef DEBUG
      printf("%d %d\n",readamount,buf[0]);
#endif
    }
}

void send_initform_strings(FILE ** serport,int numQuestions,
			   Question questions[MAXQUEST])
{
  int i, scan,j,Points;
  /* this sets up kermit and then sends the correct strings to the scantron 
     to define what the sheet looks like 
     */
  char buffer[1024],answerString[1024];
  
  for(i=0;i<1000;i++) 
    {
      buffer[i]='\0';
    }
  
  scan=11+numQuestions;
  
  /* resets the scantron*/
  sprintf(buffer,".srst\015");
  print(serport,buffer, 1);
  
  /* sets the error character to be the '"' character */
  sprintf(buffer,".err=34\015");
  print(serport,buffer, 1);
 
  /* tell scantron how many scanlines there are*/
  sprintf(buffer,".frm=fs %d 0 48 n n n\015",scan);
  print(serport,buffer, 1);
 
  /* encoded class info*/
  sprintf(buffer,".frm=pa 1 2 44 11 32 l 10 7\015");
  print(serport,buffer, 1);
 
  /* the first letter of the student number*/
  sprintf(buffer,".frm=mc n n 1 1 3 4 4 4 c 1 2 ab\015");
  print(serport,buffer, 1);
 
  /* the remaining digits of the student number*/
  sprintf(buffer,".frm=mc n n 1 1 2 6 11 20 c 8 10 0123456789\015");
  print(serport,buffer, 1);
 
  /* the PIN number*/
  sprintf(buffer,".frm=mc n n 1 1 2 24 11 30 c 4 10 0123456789\015");
  print(serport,buffer, 1);

#ifdef DEBUG
  printf("%d\n",numQuestions);
#endif /*DEBUG*/

  /*sets each question line*/
  for (i=0;i<numQuestions;i++)
    {

#ifdef DEBUG
      printf("%c\n",questions[i].type);
#endif /*DEBUG*/

      switch (questions[i].type)
	{
	case 'a':
	  sprintf(buffer,".frm=mc n m 1 1 %d 6 %d 20 l 1 8 ABCDEFGH\015",
		  i+12,i+12);
	  print(serport,buffer,1);
	  break;
	case 'b':
	  for(j=0;j<questions[i].points;j++)
	    {
	      sprintf(buffer,
		      ".frm=mc n m 1 1 %d %d %d %d l 1 3 GLE\015",
		      i+12,(j*8)+6,i+12,(j*8)+10);
	      print(serport,buffer,1);
	    }
	  break;
	case 'c':
	  for(j=0;j<questions[i].points;j++)
	    {
	      sprintf(buffer,
		      ".frm=mc n m 1 1 %d %d %d %d l 1 2 TF\015",
		      i+12,(j*6)+6,i+12,(j*6)+8);
	      print(serport,buffer,1);
	    }
	  break;
	case 'd':
	  answerString[0]='\0';
	  Points=questions[i].points;
	  for(j=0;j<=Points;j++)
	    {
	      sprintf(buffer,"%d",j);
	      strcat(answerString,buffer);
	    }
	  sprintf(buffer,".frm=mc n m 1 1 %d 6 %d %d l 1 %d %s\015",
		  i+12,i+12,(Points*2)+6,Points+1,answerString);
	  print(serport,buffer,1);
	  break;
	case 'e':
	case 'g':
	  sprintf(buffer,".frm=mc y n 1 1 %d 6 %d 20 l 1 8 ABCDEFGH\015",
		  i+12,i+12);
	  print(serport,buffer,1);
	  break;
	case 'f':
	  sprintf(buffer,".frm=mc n m 1 1 %d 6 %d 24 l 1 10 0123456789\015",
		  i+12,i+12);
	  print(serport,buffer,1);
	  break;
	default:
	  fprintf(stderr,"Booga Booga, couldn't find that question type to");
	  fprintf(stderr," tell Scantron about\n %c \n",questions[i].type);
	  break;
	}
    }

  /* end of the form*/
  sprintf(buffer,".frm=ls\015");
  print(serport,buffer, 1);
#ifdef DEBUG
  fprintf(stderr,"We have sent the data\n");
#endif /*DEBUG*/
}

void SetupScantron(FILE ** serport,int problems,
		   Question questions[MAXQUEST])
{
  serial_open(serport,"/dev/ttyfb");
  send_initform_strings(serport,problems,questions);
}

/* stolen from allpin.c and modified by Guy Albertelli*/
int buildPIDandPINlist(int setId, PIDPINlist PIDandPINlist[MAX_SECTION_SIZE] )
{
  int i=0,j=0,count=0,numStudents;
  int SecCntArry[MAX_SECTION_COUNT], sectionIdx;
  student_t Students[2048];

  if (count = capa_get_section_count(SecCntArry) != 0)
    {
      for (sectionIdx=1; sectionIdx <= SecCntArry[0]; sectionIdx++)
	{
	  numStudents=0;
	  get_section(Students, &numStudents, sectionIdx);
	  for(i=0;i<numStudents;i++,j++)
	    {
	      strcpy(PIDandPINlist[j].PID,Students[i].student_number);
	      PIDandPINlist[j].PIN=
		capa_PIN(Students[i].student_number,setId,0);
	    }
	}
    }
  return j;
}

/*searches all the possible PIN's for all matches and then asks for 
  confirmation of which PID to use*/
int findPID(Student* student,PIDPINlist PIDandPINlist[MAX_SECTION_SIZE],
	    int numOfStudents)
{
  int i,j=0,matches[30],selection,error=ENONE;
  
  for(i=0;i<numOfStudents;i++)
    {
      if (atoi(student->PIN)==PIDandPINlist[i].PIN)
	{
	  matches[j]=i;
	  j++;
	}
    }
  matches[j]=-1;
  switch(j)
    {
    case 0:
      printf("No match for PIN %s\n",student->PIN);
      error=ENOONE;
      break;
    case 1:
      printf("Only one match assuming PID %s\n",PIDandPINlist[matches[0]].PID);
      strcpy(student->questionPID,PIDandPINlist[matches[0]].PID);
      break;
    default:
      printf("Please press\n");
      for(i=0;i<30;i++)
	{
	  if (matches[i]!=-1)
	    {
	      printf("%d) for student number %s\n",i,
		     PIDandPINlist[matches[i]].PID);
	    }
	  else
	    {
	      i=30;
	    }
	}
      scanf("%d",&selection);
      if ((selection < j) && (selection > 0))
	{
	  strcpy(student->questionPID,PIDandPINlist[matches[selection]].PID);
	}
      break;
    }
  return error;
}

Student * getForm(int * status,FILE ** serport,
		  Question questions[MAXQUEST])
{
  Student *newStudent;
  char buffer[1024],buf[1024],buf2[1024];
  int readamount=0,done=0,i=0,j=0,h=0,q=0,space=0;

  sprintf(buffer,".read 2\015");
  print(serport,buffer,1);
  while(!done)
    {
      readamount=read(readportfd,buf,100);
      buf[readamount]='\0';
      for(i=0;i<readamount;i++,j++)
	{
	  if (buf[i]==13)
	    {
	      done=1;
	      break;
	    }
	  buf2[j]=buf[i];
	}
      buf2[j]='\0';
    }

  printf("%s\n",buf2);

  switch(buf2[0])
    {
    case '\"':
      *status=GFFAILED;
      return NULL;
      break;
    default:
      newStudent=(Student *)malloc(sizeof(Student));
      if (SurveyMode) 
	sprintf(newStudent->answerPID,"a%08d",formNumber++);
      else
	strncpy(newStudent->answerPID,&buf2[10],9);
      newStudent->answerPID[9]='\0';
      strncpy(newStudent->class,&buf2[2],8);
      newStudent->class[8]='\0';
      strncpy(newStudent->SetId,&buf2[0],2);
      newStudent->SetId[2]='\0';
      strncpy(newStudent->PIN,&buf2[19],4);
      newStudent->PIN[4]='\0';
      i=23;h=0;
      while(buf2[i]!='\0')
	{
	  switch(questions[h].type)
	    {
	    case 'a':
	    case 'd':
	    case 'f':
	      newStudent->Answers[h][0]=buf2[i];
	      newStudent->Answers[h][1]='\0';
	      if (isspace(buf2[i])) space++;
	      i++;
	      break;
	    case 'b':
	      /*loop through each leaf*/
	      for(j=0;j<questions[h].points;j++)
		{
		  newStudent->Answers[h][j]=buf2[i];
		  if (isspace(buf2[i])) space++;
		  i++;
		}
	      newStudent->Answers[h][j]='\0';
	      break;
	    case 'c':
	      /*loop through each leaf*/
	      for(j=0;j<questions[h].points;j++)
		{
		  newStudent->Answers[h][j]=buf2[i];
		  if (isspace(buf2[i])) space++;
		  i++;
		}
	      newStudent->Answers[h][j]='\0';
	      break;
	    case 'e':
	    case 'g':
	      for (j=0,q=0;j<8;j++)
		{
		  if (buf2[i]!=' ')
		    {
		      newStudent->Answers[h][q]=buf2[i];
		      q++;
		    }
		  i++;
		}
	      if (isspace(buf2[i])) space++;
	      newStudent->Answers[h][q]='\0';
	      break;
	    default:
	      fprintf(stderr,"Wha? %c",questions[h].type);
	      i++;
	      break;
	    }
	  h++;
	}
      *status=GFSUCCESS;
      break;
    }
  if (space!=0) *status=GFSPACES;
  return newStudent;
}

int checkForm(Student * student,int numQuestions,char *class,int setId)
{
  int error,pin;
  student_t capaStudent;

#ifdef DEBUG
  printf("PID:\t%s\nclass:\t%s\nSetId:\t%s\nPIN:\t%s\n",
	 student->answerPID,student->class,student->SetId,student->PIN);

  for(i=0,j=0;i<numQuestions;i++)
    {
      printf("Answer %d: %s\n",i,student->Answers[i]);
    }
#endif /*DEBUG*/

  if (CompareClassName)
    {
      if (strncasecmp(student->class,class,8))
	{
	  printf("Class: The Scantron reported:%s, You typed in:%s\n",
		 student->class,class);
	  return ECLASS;
	}
    }
  else
    {
      strcpy(student->class,class);
      sprintf(student->SetId,"%2d",setId);
    }

  error=capa_get_student_info(student->answerPID, &capaStudent);
  switch(error)
    {
    case 1:
      printf("%s %d\n\n",capaStudent.name,capaStudent.section);
      break;
    case 0:
      printf("PID: The Scantron reported:%s\n",student->answerPID);
      return ESTID;
      break;
    case -1:
      return ECLASSL;
      break;
    default:
      fprintf(stderr,"capa_get_student returned an invalid result ");
      fprintf(stderr,"in CheckForm.\n");
      break;
    }
  
  if (CheckPIN && !Anon)
    {
      pin=capa_PIN(student->answerPID,atoi(student->SetId),0);
      if (pin!=atoi(student->PIN))
	{
	  printf("PIN: The Scantron reported:%s, The Classl file has:%d\n",
		 student->PIN,pin);
	  return EPIN;
	}
    }
  return 0;
}

long getBubblerEntry(FILE ** outputFile,char *PID)
{
  char oneline[512],fmtbuf[16],a_sn[32];
  int done=0,found=0,offset=0,len=0,next_r=0;

  rewind(*outputFile);
  sprintf(fmtbuf,"%%%dc",MAX_STUDENT_NUMBER);
  while(!done)
    {
      done=!fgets(oneline,511,*outputFile);
      len=strlen(oneline);
      if (!done)
	{
	  sscanf(oneline,fmtbuf,a_sn);
	  if (!strncasecmp(a_sn,PID,MAX_STUDENT_NUMBER))
	    {
	      next_r=ftell(*outputFile);
	      offset = next_r-len;
	      done=1;
	      found=1;
	    }
	  else
	    {
	    }
	}
      else
	{
	  fseek(*outputFile,0L,SEEK_END);
	  offset=ftell(*outputFile);
	  fseek(*outputFile,-1L,SEEK_END);
	  while (fgetc(*outputFile)=='\n')
	    {
	      offset--;
	      fseek(*outputFile,offset,SEEK_SET);
	    }
	  offset= offset+2;
	  found=0;
	  done=1;
	}
    }
  if(!found)
    {
      offset=-offset;
    }
  return offset;
}
	  

void setBubblerEntry(FILE ** outputFile,char* answerPID,char* name,
		     char* answers,int score, int section, 
		     char* answerstring,char* questionPID, int offset)
{
  int len=0;
  char buf[1024];
  
  rewind(*outputFile);
  sprintf(buf,"%s %s %s %3d %2d %s %s\n",answerPID,name,answers,score,section,
	  answerstring,questionPID);
  len=strlen(buf);
  fseek(*outputFile,abs(offset),0);
  if(!fwrite(buf,len,1,*outputFile))
    {
      fprintf(stderr,"Failed write.\n");
    }
}
     

/* Checks if answers are right and gives a point for each right.*/
void writeForm(Student * student,FILE ** outputFile,
	       Question questions[MAXQUEST],int numQuestions)
{
  int result,capaQuestions,questionIndex,leafs,numRight,error,total=0;
  int offset2;
  char one=1,zero=0;
  char *ansOn[20],*stuOn[20];
  Problem_t *problems,*oldproblem;
  char answerstring[1024],grade[1024];
  student_t capaStudent;

  if (!SurveyMode)
    {
      error=capa_get_student_info(student->answerPID, &capaStudent);
      result=capa_parse(atoi(student->SetId),&problems,student->questionPID,
			&capaQuestions);
      oldproblem=problems;
      if (result==0)
	{
	  fprintf(stderr,"Parse failed: %d\n",result);
	  return;
	}
    }
  else
    {
      strcpy(capaStudent.name,"Unknown                       ");
      capaStudent.section=0;
      oldproblem=problems=NULL;      
    }
  offset2=getBubblerEntry(outputFile,student->answerPID);
  for(questionIndex=0;questionIndex<numQuestions;questionIndex++)
    {
      switch(questions[questionIndex].type)
	{
	case 'a':
	case 'b':
	case 'c':
	case 'f':
	  numRight=0;
	  printf("%s %s\n",problems->answer,student->Answers[questionIndex]);
	  for(leafs=0;problems->answer[leafs]!='\0';leafs++)
	    {
	      if (problems->answer[leafs]==
		  student->Answers[questionIndex][leafs])
		{
		  numRight++;
		}
	    }
	  total+=numRight;
	  grade[questionIndex]='0'+(char)numRight;
	  break;
	case 'd':
	  printf("%s\n",student->Answers[questionIndex]);
	  grade[questionIndex]=student->Answers[questionIndex][0];
	  if (isspace(student->Answers[questionIndex][0]))
	    total+=0;
	  else
	    total+=(int)(student->Answers[questionIndex][0]-'0');
	  break;
	case 'e':
	  printf("%s %s\n",problems->answer,student->Answers[questionIndex]);
	  numRight=0;
	  for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
	    {
	      ansOn[leafs]=strchr(problems->answer,('A'+(char)leafs));
	    }
	  for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
	    {
	      if (ansOn[leafs] != NULL ) { ansOn[leafs]=&one;} 
	      else { ansOn[leafs]=&zero;}
	    }
	  for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
	    {
	      stuOn[leafs]=strchr(student->Answers[questionIndex],
				  ('A'+(char)leafs));
	    }
	  for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
	    {
	      if (stuOn[leafs] != NULL) {stuOn[leafs]=&one;} 
	      else {stuOn[leafs]=&zero;}
	    }
	  for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
	    {
	      if (ansOn[leafs] == stuOn[leafs]) numRight++;
	    }
	  fprintf(stderr,"%d\n",numRight);
	  total+=numRight;
	  grade[questionIndex]='0'+(char)numRight;
	  break;
	case 'g':
	  printf("%s %s\n",problems->answer,student->Answers[questionIndex]);
	  if (!(strcasecmp(problems->answer,student->Answers[questionIndex])))
	    {
	      total+=questions[questionIndex].points;
	      grade[questionIndex]='0'+questions[questionIndex].points;
	    }
	  else
	    {
	      grade[questionIndex]='0';
	    }
	  break;
	default:
	  printf("No points since don't know question type.\n");
	  break;
	}
      if (!SurveyMode) problems=problems->next;
    }

  answerstring[0]='\0';

  for(questionIndex=0;questionIndex<numQuestions;questionIndex++)
    {
      strcat(answerstring,student->Answers[questionIndex]);
    }
     
  setBubblerEntry(outputFile,student->answerPID,capaStudent.name,grade,
		  total,capaStudent.section,answerstring,student->questionPID,
		  offset2);

  if (!SurveyMode)
    {
      problems=oldproblem;
      for(questionIndex=0;problems!=NULL;questionIndex++)
	{
	  oldproblem=problems;
	  problems=problems->next;
	  free(oldproblem);
	}
#ifdef DEBUG
      fprintf(stderr,"Freed: %d\n",questionIndex);
#endif /*DEBUG*/
    }
}

void processForms(FILE ** serport,int numQuestions,
		  Question questions[MAXQUEST],char* class,int setId)
{

  int done=0,error,i,numOfStudents=0;
  int status;
  char buf[128],filename[128];
  Student * student;
  FILE * outputFile;
  PIDPINlist PIDandPINlist[MAX_SECTION_SIZE];

  sprintf(filename,"bubbler.output.%d",setId);
  outputFile=fopen(filename,"r+");
  if (outputFile != NULL)
    {
      rewind(outputFile);
      fscanf(outputFile,"%s",buf);
    }
  if (outputFile==NULL || buf[0]=='\0')
    {
      outputFile=fopen(filename,"w+");
      fprintf(outputFile,"%s %d ",class,setId);
      for(i=0;i<numQuestions;i++)
	{
	  fprintf(outputFile,"%c%d",questions[i].type,questions[i].points);
	}
      fprintf(outputFile,"\n");
    }
  if (Anon)
    {
      numOfStudents=buildPIDandPINlist(setId,PIDandPINlist);
      if (numOfStudents==0)
	{
	  fprintf(stderr,"buildPIDandPINlists returned 0 students.");
	  exit(-2);
	}
    }
  
  while(!done)
    {
      student=getForm(&status,serport,questions);
      switch (status)
	{
	case GFSPACES:
	  if (CheckSpaces)
	    {
	      printf("The current form appears to have some questions left\n");
	      printf("blank. Please enter yes if you wish to continue \n");
	      printf("grading of this form.\n");
	      scanf("%s",buf);
	      if (buf[0]=='y' || buf[0]=='Y') ;
	      else break;
	    }
	case GFSUCCESS:
	  if ((!SurveyMode) && 
	      (error=checkForm(student,numQuestions,class,setId))) 
	    {
	      switch(error)
		{
		case ECLASS:
		  printf("The current form has a class string that is \n");
		  printf("different from the one entered at the start.\n");
		  printf("Please place that form to the side and type ");
		  printf("start to continue.\n");
		  scanf("%s",buf);
		  break;
		case ESTID:
		  printf("The current form's Student Id is incorrect.\n");
		  printf("Please set the form aside and type start to ");
		  printf("continue.\n");
		  scanf("%s",buf);
		  break;
		case ECLASSL:
		  fprintf(stderr,"The classl file was not found in the");
		  fprintf(stderr," current directory.\n");
		  fprintf(stderr,"Please try again.\n");
		  done=1;
		  break;
		case EPIN:
		  fprintf(stderr,"The current form's PIN is incorrect.\n");
		  fprintf(stderr,"Please set the form aside and type ");
		  fprintf(stderr,"start to continue.\n");
		  scanf("%s",buf);
		  break;
		default:
		  fprintf(stderr,"Unimplemented error in checkForm %d\n",
			  error);
		  break;
		}
	    }
	  else
	    {
	      if (Anon)
		{
		  error=findPID(student,PIDandPINlist,numOfStudents);
		}
	      else
		{
		  error=ENONE;
		  strcpy(student->questionPID,student->answerPID);
		}
	      switch(error)
		{
		case ENONE:
		  writeForm(student,&outputFile,questions,numQuestions);
		  break;
		case ENOONE:
		  break;
		default:
		  fprintf(stderr,"Unimplemented error in findPID %d\n",
			  error);
		  break;
		}
	    }
	  break;
	case GFFAILED:
	  printf("The Scantron has returned an error.\n");
	  printf("Are there still more forms to process?");
	  scanf("%s",buf);
	  if (buf[0]=='n')
	    {
	      done=1;
	    }
	  else
	    {
	      printf("Please put that last read form to the side.\n");
	      printf("Enter start to continue\n");
	      scanf("%s",buf);
	    }
	  break;
	case GFEOF:
	  done=1;
	  break;
	default:
	  printf("Unimplened return code in GetForm %d\n",status);
	  break;
	}
      if (student != NULL)
	{
	  free(student);
	}
    }
}

void CloseScantron(FILE ** serport)
{
  fprintf(*serport,".srst\r");
  fclose(*serport);
}

int main(int argc, char *argv[])
{
  FILE * serport;
  Question questions[MAXQUEST];
  char class[10];
  int numQuestions,setId;

  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\n\n");
  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\n\n");
  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\n\n");
  printf("Welcome to Bubbler, the Automated CAPA grader.\n");
  printf("Version 0.05.02\n\n\n");
  numQuestions=GetProblems(questions,class,&setId);
  SetupScantron(&serport,numQuestions,questions);
  processForms(&serport,numQuestions,questions,class,setId);
  CloseScantron(&serport);
  return 0;
}


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.