Annotation of capa/capa51/Historic/bubbler.c, revision 1.3

1.1       albertel    1: #include <stdio.h>
                      2: #include <sgtty.h>
                      3: #include <libc.h>
                      4: #include <sys/types.h>
                      5: #include <sys/uio.h>
                      6: #include <ctype.h>
                      7: #include "Capa/capaCommon.h"
                      8: #include "bubbler.h"
1.2       albertel    9: /* scantron control program
                     10:    Copyright (C) 1992-2000 Michigan State University
                     11: 
                     12:    The CAPA system is free software; you can redistribute it and/or
1.3     ! albertel   13:    modify it under the terms of the GNU General Public License as
1.2       albertel   14:    published by the Free Software Foundation; either version 2 of the
                     15:    License, or (at your option) any later version.
                     16: 
                     17:    The CAPA system is distributed in the hope that it will be useful,
                     18:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     19:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1.3     ! albertel   20:    General Public License for more details.
1.2       albertel   21: 
1.3     ! albertel   22:    You should have received a copy of the GNU General Public
1.2       albertel   23:    License along with the CAPA system; see the file COPYING.  If not,
                     24:    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
                     25:    Boston, MA 02111-1307, USA.
                     26: 
                     27:    As a special exception, you have permission to link this program
                     28:    with the TtH/TtM library and distribute executables, as long as you
                     29:    follow the requirements of the GNU GPL in regard to all of the
                     30:    software in the executable aside from TtH/TtM.
                     31: */
1.1       albertel   32: 
                     33: int serportfd;
                     34: int readportfd;
                     35: FILE * readport;
                     36: int CheckPIN;
                     37: int CompareClassName;
                     38: int Anon;
                     39: int CheckSpaces;
                     40: int SurveyMode;
                     41: int SurveyHeader;
                     42: int formNumber;
                     43: 
                     44: int GetProblems(Question questions[MAXQUEST],char * class,int * setId)
                     45: {
                     46:   int i,q,length;
                     47:   char clear[100];
                     48: 
                     49:   printf("What is the class name?");
                     50:   scanf("%s",class);
                     51:   
                     52:   printf("What is the SetId?");
                     53:   scanf("%d",setId);
                     54: 
                     55:   printf("Is this a survey or exam/quiz?(s or e)");
                     56:   scanf("%s",clear);
                     57:   if (clear[0]=='s' || clear[0]=='S')
                     58:     {
                     59:       SurveyMode=1;
                     60:       printf("Does the form include a Header?(y or n)");
                     61:       scanf("%s",clear);
                     62:       if (clear[0]=='n' || clear[0]=='N')
                     63: 	{
                     64: 	  SurveyHeader=0;
                     65: 	}
                     66:       else
                     67: 	{
                     68: 	  SurveyHeader=1;
                     69: 	}
                     70:       printf("How many Questions are on the form?");
                     71:       scanf("%d",&q);
                     72:       
                     73:       for (i=0;i<q;i++)
                     74: 	{
                     75: 	  questions[i].type='d';
                     76: 	  questions[i].leafs=questions[i].points=9;
                     77: 	}
                     78:     }
                     79:   else
                     80:     {
                     81:       SurveyMode=0;
                     82: 
                     83:       printf("Should bubbler compare the entered class name and SetId with \n");
                     84:       printf("the encoded information on each paper?(y or n)");
                     85:       scanf("%s",clear);
                     86:       if (clear[0]=='N' || clear[0]=='n')
                     87: 	CompareClassName=0;
                     88:       else
                     89: 	CompareClassName=1;
                     90:       
                     91:       printf("Should the student coded CAPA ID be checked for correctness?\n");
                     92:       printf("(y or n)");
                     93:       scanf("%s",clear);
                     94:       if (clear[0]=='N' || clear[0]=='n')
                     95: 	CheckPIN=0;
                     96:       else
                     97: 	{
                     98: 	  CheckPIN=1;
                     99: 	  
                    100: 	  printf("Should bubbler run in Anonymous mode (search for correct \n");
                    101: 	  printf("Student Number based on the CAPA ID)? (y or n)");
                    102: 	  scanf("%s",clear);
                    103: 	  
                    104: 	  if (clear[0]=='N' || clear[0]=='n')
                    105: 	    Anon=0;
                    106: 	  else
                    107: 	    Anon=1;
                    108: 	}
                    109:       
                    110:       printf("Should bubbler check for blank answers and issue a warning when \n");
                    111:       printf("one is encountered? (y or n)");
                    112:       scanf("%s",clear);
                    113:       if (clear[0]=='N' || clear[0]=='n')
                    114: 	CheckSpaces=0;
                    115:       else
                    116: 	CheckSpaces=1;
                    117:       
                    118:       length=strlen(class);
                    119:       if (length < 8)
                    120: 	{
                    121: 	  for(;length<8;length++)
                    122: 	    {
                    123: 	      class[length]=' ';
                    124: 	    }
                    125: 	  class[length]='\0';
                    126: 	}
                    127:       printf("How many Questions are on the form?");
                    128:       scanf("%d",&q);
                    129:       
                    130:       printf("For Each Question enter \"a\" for a one out of 8\n");
                    131:       printf("                        \"b\" for a GLE type\n");
                    132:       printf("                        \"c\" for a TF type.\n");
                    133:       printf("                        \"d\" for an assigned score.\n");
                    134:       printf("                        \"e\" for a multiple out of 8.\n");
                    135:       printf("                        \"f\" for single digit string matching.\n");
                    136:       printf("                        \"g\" for exact string matching/\n");
                    137:       
                    138:       for (i=0;i<q;i++)
                    139: 	{
                    140: 	  printf("Question#%2d: ",i+1);
                    141: 	  scanf("%1s",&questions[i].type);
                    142: 	  fflush(stdin);
                    143: 	  switch(questions[i].type)
                    144: 	    {
                    145: 	    case 'a':
                    146: 	    case 'd':
                    147: 	    case 'g':
                    148: 	    case 'f':
                    149: 	      printf("How many Points are possible?");
                    150: 	      scanf("%d",&questions[i].points);
                    151: 	      questions[i].leafs=questions[i].points;
                    152: 	      break;
                    153: 	    case 'b':
                    154: 	    case 'c':
                    155: 	      printf("How many parts to the problem?");
                    156: 	      scanf("%d",&questions[i].points);
                    157: 	      questions[i].leafs=questions[i].points;
                    158: 	      break;
                    159: 	    case 'e':
                    160: 	      printf("How many possible answers are there?");
                    161: 	      scanf("%d",&questions[i].points);
                    162: 	      questions[i].leafs=questions[i].points;
                    163: 	      break;
                    164: 	    default:
                    165: 	      printf("Unknown choice.\n");
                    166: 	      break;
                    167: 	    }
                    168: 	  fflush(stdin);
                    169: 	}
                    170:     }
                    171:   return q;
                    172: }
                    173:  
                    174: void serial_open(FILE ** streamserport,char * device)
                    175: {
                    176:   struct sgttyb one;
                    177:   
                    178:   if ((serportfd=open(device,O_WRONLY,O_CREAT))==-1)
                    179:     {
                    180:       fprintf(stderr,"Unable to open serial port.\n");
                    181:       exit(-1);
                    182:     }
                    183: 
                    184:   if ((readportfd=open(device,O_RDONLY,O_CREAT))==-1)
                    185:     {
                    186:       fprintf(stderr,"Unable to open serial port for reading.\n");
                    187:       exit(-1);
                    188:     }
                    189:   
                    190:   one.sg_ispeed='\015';
                    191:   one.sg_ospeed='\015';
                    192:   one.sg_erase='\177';
                    193:   one.sg_kill='\024';
                    194:   one.sg_flags= (short) 3;
                    195: 
                    196: #ifdef DEBUG  
                    197:   ioctl(serportfd,TIOCGETP,&two);
                    198:   printf("%d %d %d %d %d\n",two.sg_ispeed,two.sg_ospeed,
                    199: 	 two.sg_erase,two.sg_kill,two.sg_flags);
                    200: #endif
                    201:   
                    202:   ioctl(serportfd,TIOCSETN,&one);
                    203:   ioctl(readportfd,TIOCSETN,&one);
                    204: 
                    205: #ifdef DEBUG
                    206:   ioctl(serportfd,TIOCGETP,&two);
                    207:   printf("%d %d %d %d %d\n",two.sg_ispeed,two.sg_ospeed,
                    208: 	 two.sg_erase,two.sg_kill,two.sg_flags);
                    209:   printf("%d %d %d %d %d\n",one.sg_ispeed,one.sg_ospeed,
                    210: 	 one.sg_erase,one.sg_kill,one.sg_flags);
                    211: #endif
                    212:   *streamserport=fdopen(serportfd,"w");
                    213:   readport=fdopen(readportfd,"r");
                    214: }
                    215: 
                    216: 
                    217: void print(FILE** serport,char * out,int shouldread)
                    218: {
                    219:   int readamount;
                    220:   char buf[100];
                    221: 
                    222: #ifdef DEBUG
                    223:   printf("%s\n",out);
                    224: #endif /*DEBUG*/
                    225: 
                    226:   write(serportfd,out,strlen(out));
                    227:   if (shouldread)
                    228:     {
                    229:       readamount=read(readportfd,buf,1);
                    230: #ifdef DEBUG
                    231:       printf("%d %d\n",readamount,buf[0]);
                    232: #endif
                    233:     }
                    234: }
                    235: 
                    236: void send_initform_strings(FILE ** serport,int numQuestions,
                    237: 			   Question questions[MAXQUEST])
                    238: {
                    239:   int i, scan,j,Points;
                    240:   /* this sets up kermit and then sends the correct strings to the scantron 
                    241:      to define what the sheet looks like 
                    242:      */
                    243:   char buffer[1024],answerString[1024];
                    244:   
                    245:   for(i=0;i<1000;i++) 
                    246:     {
                    247:       buffer[i]='\0';
                    248:     }
                    249:   
                    250:   scan=11+numQuestions;
                    251:   
                    252:   /* resets the scantron*/
                    253:   sprintf(buffer,".srst\015");
                    254:   print(serport,buffer, 1);
                    255:   
                    256:   /* sets the error character to be the '"' character */
                    257:   sprintf(buffer,".err=34\015");
                    258:   print(serport,buffer, 1);
                    259:  
                    260:   /* tell scantron how many scanlines there are*/
                    261:   sprintf(buffer,".frm=fs %d 0 48 n n n\015",scan);
                    262:   print(serport,buffer, 1);
                    263:  
                    264:   /* encoded class info*/
                    265:   sprintf(buffer,".frm=pa 1 2 44 11 32 l 10 7\015");
                    266:   print(serport,buffer, 1);
                    267:  
                    268:   /* the first letter of the student number*/
                    269:   sprintf(buffer,".frm=mc n n 1 1 3 4 4 4 c 1 2 ab\015");
                    270:   print(serport,buffer, 1);
                    271:  
                    272:   /* the remaining digits of the student number*/
                    273:   sprintf(buffer,".frm=mc n n 1 1 2 6 11 20 c 8 10 0123456789\015");
                    274:   print(serport,buffer, 1);
                    275:  
                    276:   /* the PIN number*/
                    277:   sprintf(buffer,".frm=mc n n 1 1 2 24 11 30 c 4 10 0123456789\015");
                    278:   print(serport,buffer, 1);
                    279: 
                    280: #ifdef DEBUG
                    281:   printf("%d\n",numQuestions);
                    282: #endif /*DEBUG*/
                    283: 
                    284:   /*sets each question line*/
                    285:   for (i=0;i<numQuestions;i++)
                    286:     {
                    287: 
                    288: #ifdef DEBUG
                    289:       printf("%c\n",questions[i].type);
                    290: #endif /*DEBUG*/
                    291: 
                    292:       switch (questions[i].type)
                    293: 	{
                    294: 	case 'a':
                    295: 	  sprintf(buffer,".frm=mc n m 1 1 %d 6 %d 20 l 1 8 ABCDEFGH\015",
                    296: 		  i+12,i+12);
                    297: 	  print(serport,buffer,1);
                    298: 	  break;
                    299: 	case 'b':
                    300: 	  for(j=0;j<questions[i].points;j++)
                    301: 	    {
                    302: 	      sprintf(buffer,
                    303: 		      ".frm=mc n m 1 1 %d %d %d %d l 1 3 GLE\015",
                    304: 		      i+12,(j*8)+6,i+12,(j*8)+10);
                    305: 	      print(serport,buffer,1);
                    306: 	    }
                    307: 	  break;
                    308: 	case 'c':
                    309: 	  for(j=0;j<questions[i].points;j++)
                    310: 	    {
                    311: 	      sprintf(buffer,
                    312: 		      ".frm=mc n m 1 1 %d %d %d %d l 1 2 TF\015",
                    313: 		      i+12,(j*6)+6,i+12,(j*6)+8);
                    314: 	      print(serport,buffer,1);
                    315: 	    }
                    316: 	  break;
                    317: 	case 'd':
                    318: 	  answerString[0]='\0';
                    319: 	  Points=questions[i].points;
                    320: 	  for(j=0;j<=Points;j++)
                    321: 	    {
                    322: 	      sprintf(buffer,"%d",j);
                    323: 	      strcat(answerString,buffer);
                    324: 	    }
                    325: 	  sprintf(buffer,".frm=mc n m 1 1 %d 6 %d %d l 1 %d %s\015",
                    326: 		  i+12,i+12,(Points*2)+6,Points+1,answerString);
                    327: 	  print(serport,buffer,1);
                    328: 	  break;
                    329: 	case 'e':
                    330: 	case 'g':
                    331: 	  sprintf(buffer,".frm=mc y n 1 1 %d 6 %d 20 l 1 8 ABCDEFGH\015",
                    332: 		  i+12,i+12);
                    333: 	  print(serport,buffer,1);
                    334: 	  break;
                    335: 	case 'f':
                    336: 	  sprintf(buffer,".frm=mc n m 1 1 %d 6 %d 24 l 1 10 0123456789\015",
                    337: 		  i+12,i+12);
                    338: 	  print(serport,buffer,1);
                    339: 	  break;
                    340: 	default:
                    341: 	  fprintf(stderr,"Booga Booga, couldn't find that question type to");
                    342: 	  fprintf(stderr," tell Scantron about\n %c \n",questions[i].type);
                    343: 	  break;
                    344: 	}
                    345:     }
                    346: 
                    347:   /* end of the form*/
                    348:   sprintf(buffer,".frm=ls\015");
                    349:   print(serport,buffer, 1);
                    350: #ifdef DEBUG
                    351:   fprintf(stderr,"We have sent the data\n");
                    352: #endif /*DEBUG*/
                    353: }
                    354: 
                    355: void SetupScantron(FILE ** serport,int problems,
                    356: 		   Question questions[MAXQUEST])
                    357: {
                    358:   serial_open(serport,"/dev/ttyfb");
                    359:   send_initform_strings(serport,problems,questions);
                    360: }
                    361: 
                    362: /* stolen from allpin.c and modified by Guy Albertelli*/
                    363: int buildPIDandPINlist(int setId, PIDPINlist PIDandPINlist[MAX_SECTION_SIZE] )
                    364: {
                    365:   int i=0,j=0,count=0,numStudents;
                    366:   int SecCntArry[MAX_SECTION_COUNT], sectionIdx;
                    367:   student_t Students[2048];
                    368: 
                    369:   if (count = capa_get_section_count(SecCntArry) != 0)
                    370:     {
                    371:       for (sectionIdx=1; sectionIdx <= SecCntArry[0]; sectionIdx++)
                    372: 	{
                    373: 	  numStudents=0;
                    374: 	  get_section(Students, &numStudents, sectionIdx);
                    375: 	  for(i=0;i<numStudents;i++,j++)
                    376: 	    {
                    377: 	      strcpy(PIDandPINlist[j].PID,Students[i].student_number);
                    378: 	      PIDandPINlist[j].PIN=
                    379: 		capa_PIN(Students[i].student_number,setId,0);
                    380: 	    }
                    381: 	}
                    382:     }
                    383:   return j;
                    384: }
                    385: 
                    386: /*searches all the possible PIN's for all matches and then asks for 
                    387:   confirmation of which PID to use*/
                    388: int findPID(Student* student,PIDPINlist PIDandPINlist[MAX_SECTION_SIZE],
                    389: 	    int numOfStudents)
                    390: {
                    391:   int i,j=0,matches[30],selection,error=ENONE;
                    392:   
                    393:   for(i=0;i<numOfStudents;i++)
                    394:     {
                    395:       if (atoi(student->PIN)==PIDandPINlist[i].PIN)
                    396: 	{
                    397: 	  matches[j]=i;
                    398: 	  j++;
                    399: 	}
                    400:     }
                    401:   matches[j]=-1;
                    402:   switch(j)
                    403:     {
                    404:     case 0:
                    405:       printf("No match for PIN %s\n",student->PIN);
                    406:       error=ENOONE;
                    407:       break;
                    408:     case 1:
                    409:       printf("Only one match assuming PID %s\n",PIDandPINlist[matches[0]].PID);
                    410:       strcpy(student->questionPID,PIDandPINlist[matches[0]].PID);
                    411:       break;
                    412:     default:
                    413:       printf("Please press\n");
                    414:       for(i=0;i<30;i++)
                    415: 	{
                    416: 	  if (matches[i]!=-1)
                    417: 	    {
                    418: 	      printf("%d) for student number %s\n",i,
                    419: 		     PIDandPINlist[matches[i]].PID);
                    420: 	    }
                    421: 	  else
                    422: 	    {
                    423: 	      i=30;
                    424: 	    }
                    425: 	}
                    426:       scanf("%d",&selection);
                    427:       if ((selection < j) && (selection > 0))
                    428: 	{
                    429: 	  strcpy(student->questionPID,PIDandPINlist[matches[selection]].PID);
                    430: 	}
                    431:       break;
                    432:     }
                    433:   return error;
                    434: }
                    435: 
                    436: Student * getForm(int * status,FILE ** serport,
                    437: 		  Question questions[MAXQUEST])
                    438: {
                    439:   Student *newStudent;
                    440:   char buffer[1024],buf[1024],buf2[1024];
                    441:   int readamount=0,done=0,i=0,j=0,h=0,q=0,space=0;
                    442: 
                    443:   sprintf(buffer,".read 2\015");
                    444:   print(serport,buffer,1);
                    445:   while(!done)
                    446:     {
                    447:       readamount=read(readportfd,buf,100);
                    448:       buf[readamount]='\0';
                    449:       for(i=0;i<readamount;i++,j++)
                    450: 	{
                    451: 	  if (buf[i]==13)
                    452: 	    {
                    453: 	      done=1;
                    454: 	      break;
                    455: 	    }
                    456: 	  buf2[j]=buf[i];
                    457: 	}
                    458:       buf2[j]='\0';
                    459:     }
                    460: 
                    461:   printf("%s\n",buf2);
                    462: 
                    463:   switch(buf2[0])
                    464:     {
                    465:     case '\"':
                    466:       *status=GFFAILED;
                    467:       return NULL;
                    468:       break;
                    469:     default:
                    470:       newStudent=(Student *)malloc(sizeof(Student));
                    471:       if (SurveyMode) 
                    472: 	sprintf(newStudent->answerPID,"a%08d",formNumber++);
                    473:       else
                    474: 	strncpy(newStudent->answerPID,&buf2[10],9);
                    475:       newStudent->answerPID[9]='\0';
                    476:       strncpy(newStudent->class,&buf2[2],8);
                    477:       newStudent->class[8]='\0';
                    478:       strncpy(newStudent->SetId,&buf2[0],2);
                    479:       newStudent->SetId[2]='\0';
                    480:       strncpy(newStudent->PIN,&buf2[19],4);
                    481:       newStudent->PIN[4]='\0';
                    482:       i=23;h=0;
                    483:       while(buf2[i]!='\0')
                    484: 	{
                    485: 	  switch(questions[h].type)
                    486: 	    {
                    487: 	    case 'a':
                    488: 	    case 'd':
                    489: 	    case 'f':
                    490: 	      newStudent->Answers[h][0]=buf2[i];
                    491: 	      newStudent->Answers[h][1]='\0';
                    492: 	      if (isspace(buf2[i])) space++;
                    493: 	      i++;
                    494: 	      break;
                    495: 	    case 'b':
                    496: 	      /*loop through each leaf*/
                    497: 	      for(j=0;j<questions[h].points;j++)
                    498: 		{
                    499: 		  newStudent->Answers[h][j]=buf2[i];
                    500: 		  if (isspace(buf2[i])) space++;
                    501: 		  i++;
                    502: 		}
                    503: 	      newStudent->Answers[h][j]='\0';
                    504: 	      break;
                    505: 	    case 'c':
                    506: 	      /*loop through each leaf*/
                    507: 	      for(j=0;j<questions[h].points;j++)
                    508: 		{
                    509: 		  newStudent->Answers[h][j]=buf2[i];
                    510: 		  if (isspace(buf2[i])) space++;
                    511: 		  i++;
                    512: 		}
                    513: 	      newStudent->Answers[h][j]='\0';
                    514: 	      break;
                    515: 	    case 'e':
                    516: 	    case 'g':
                    517: 	      for (j=0,q=0;j<8;j++)
                    518: 		{
                    519: 		  if (buf2[i]!=' ')
                    520: 		    {
                    521: 		      newStudent->Answers[h][q]=buf2[i];
                    522: 		      q++;
                    523: 		    }
                    524: 		  i++;
                    525: 		}
                    526: 	      if (isspace(buf2[i])) space++;
                    527: 	      newStudent->Answers[h][q]='\0';
                    528: 	      break;
                    529: 	    default:
                    530: 	      fprintf(stderr,"Wha? %c",questions[h].type);
                    531: 	      i++;
                    532: 	      break;
                    533: 	    }
                    534: 	  h++;
                    535: 	}
                    536:       *status=GFSUCCESS;
                    537:       break;
                    538:     }
                    539:   if (space!=0) *status=GFSPACES;
                    540:   return newStudent;
                    541: }
                    542: 
                    543: int checkForm(Student * student,int numQuestions,char *class,int setId)
                    544: {
                    545:   int error,pin;
                    546:   student_t capaStudent;
                    547: 
                    548: #ifdef DEBUG
                    549:   printf("PID:\t%s\nclass:\t%s\nSetId:\t%s\nPIN:\t%s\n",
                    550: 	 student->answerPID,student->class,student->SetId,student->PIN);
                    551: 
                    552:   for(i=0,j=0;i<numQuestions;i++)
                    553:     {
                    554:       printf("Answer %d: %s\n",i,student->Answers[i]);
                    555:     }
                    556: #endif /*DEBUG*/
                    557: 
                    558:   if (CompareClassName)
                    559:     {
                    560:       if (strncasecmp(student->class,class,8))
                    561: 	{
                    562: 	  printf("Class: The Scantron reported:%s, You typed in:%s\n",
                    563: 		 student->class,class);
                    564: 	  return ECLASS;
                    565: 	}
                    566:     }
                    567:   else
                    568:     {
                    569:       strcpy(student->class,class);
                    570:       sprintf(student->SetId,"%2d",setId);
                    571:     }
                    572: 
                    573:   error=capa_get_student_info(student->answerPID, &capaStudent);
                    574:   switch(error)
                    575:     {
                    576:     case 1:
                    577:       printf("%s %d\n\n",capaStudent.name,capaStudent.section);
                    578:       break;
                    579:     case 0:
                    580:       printf("PID: The Scantron reported:%s\n",student->answerPID);
                    581:       return ESTID;
                    582:       break;
                    583:     case -1:
                    584:       return ECLASSL;
                    585:       break;
                    586:     default:
                    587:       fprintf(stderr,"capa_get_student returned an invalid result ");
                    588:       fprintf(stderr,"in CheckForm.\n");
                    589:       break;
                    590:     }
                    591:   
                    592:   if (CheckPIN && !Anon)
                    593:     {
                    594:       pin=capa_PIN(student->answerPID,atoi(student->SetId),0);
                    595:       if (pin!=atoi(student->PIN))
                    596: 	{
                    597: 	  printf("PIN: The Scantron reported:%s, The Classl file has:%d\n",
                    598: 		 student->PIN,pin);
                    599: 	  return EPIN;
                    600: 	}
                    601:     }
                    602:   return 0;
                    603: }
                    604: 
                    605: long getBubblerEntry(FILE ** outputFile,char *PID)
                    606: {
                    607:   char oneline[512],fmtbuf[16],a_sn[32];
                    608:   int done=0,found=0,offset=0,len=0,next_r=0;
                    609: 
                    610:   rewind(*outputFile);
                    611:   sprintf(fmtbuf,"%%%dc",MAX_STUDENT_NUMBER);
                    612:   while(!done)
                    613:     {
                    614:       done=!fgets(oneline,511,*outputFile);
                    615:       len=strlen(oneline);
                    616:       if (!done)
                    617: 	{
                    618: 	  sscanf(oneline,fmtbuf,a_sn);
                    619: 	  if (!strncasecmp(a_sn,PID,MAX_STUDENT_NUMBER))
                    620: 	    {
                    621: 	      next_r=ftell(*outputFile);
                    622: 	      offset = next_r-len;
                    623: 	      done=1;
                    624: 	      found=1;
                    625: 	    }
                    626: 	  else
                    627: 	    {
                    628: 	    }
                    629: 	}
                    630:       else
                    631: 	{
                    632: 	  fseek(*outputFile,0L,SEEK_END);
                    633: 	  offset=ftell(*outputFile);
                    634: 	  fseek(*outputFile,-1L,SEEK_END);
                    635: 	  while (fgetc(*outputFile)=='\n')
                    636: 	    {
                    637: 	      offset--;
                    638: 	      fseek(*outputFile,offset,SEEK_SET);
                    639: 	    }
                    640: 	  offset= offset+2;
                    641: 	  found=0;
                    642: 	  done=1;
                    643: 	}
                    644:     }
                    645:   if(!found)
                    646:     {
                    647:       offset=-offset;
                    648:     }
                    649:   return offset;
                    650: }
                    651: 	  
                    652: 
                    653: void setBubblerEntry(FILE ** outputFile,char* answerPID,char* name,
                    654: 		     char* answers,int score, int section, 
                    655: 		     char* answerstring,char* questionPID, int offset)
                    656: {
                    657:   int len=0;
                    658:   char buf[1024];
                    659:   
                    660:   rewind(*outputFile);
                    661:   sprintf(buf,"%s %s %s %3d %2d %s %s\n",answerPID,name,answers,score,section,
                    662: 	  answerstring,questionPID);
                    663:   len=strlen(buf);
                    664:   fseek(*outputFile,abs(offset),0);
                    665:   if(!fwrite(buf,len,1,*outputFile))
                    666:     {
                    667:       fprintf(stderr,"Failed write.\n");
                    668:     }
                    669: }
                    670:      
                    671: 
                    672: /* Checks if answers are right and gives a point for each right.*/
                    673: void writeForm(Student * student,FILE ** outputFile,
                    674: 	       Question questions[MAXQUEST],int numQuestions)
                    675: {
                    676:   int result,capaQuestions,questionIndex,leafs,numRight,error,total=0;
                    677:   int offset2;
                    678:   char one=1,zero=0;
                    679:   char *ansOn[20],*stuOn[20];
                    680:   Problem_t *problems,*oldproblem;
                    681:   char answerstring[1024],grade[1024];
                    682:   student_t capaStudent;
                    683: 
                    684:   if (!SurveyMode)
                    685:     {
                    686:       error=capa_get_student_info(student->answerPID, &capaStudent);
                    687:       result=capa_parse(atoi(student->SetId),&problems,student->questionPID,
                    688: 			&capaQuestions);
                    689:       oldproblem=problems;
                    690:       if (result==0)
                    691: 	{
                    692: 	  fprintf(stderr,"Parse failed: %d\n",result);
                    693: 	  return;
                    694: 	}
                    695:     }
                    696:   else
                    697:     {
                    698:       strcpy(capaStudent.name,"Unknown                       ");
                    699:       capaStudent.section=0;
                    700:       oldproblem=problems=NULL;      
                    701:     }
                    702:   offset2=getBubblerEntry(outputFile,student->answerPID);
                    703:   for(questionIndex=0;questionIndex<numQuestions;questionIndex++)
                    704:     {
                    705:       switch(questions[questionIndex].type)
                    706: 	{
                    707: 	case 'a':
                    708: 	case 'b':
                    709: 	case 'c':
                    710: 	case 'f':
                    711: 	  numRight=0;
                    712: 	  printf("%s %s\n",problems->answer,student->Answers[questionIndex]);
                    713: 	  for(leafs=0;problems->answer[leafs]!='\0';leafs++)
                    714: 	    {
                    715: 	      if (problems->answer[leafs]==
                    716: 		  student->Answers[questionIndex][leafs])
                    717: 		{
                    718: 		  numRight++;
                    719: 		}
                    720: 	    }
                    721: 	  total+=numRight;
                    722: 	  grade[questionIndex]='0'+(char)numRight;
                    723: 	  break;
                    724: 	case 'd':
                    725: 	  printf("%s\n",student->Answers[questionIndex]);
                    726: 	  grade[questionIndex]=student->Answers[questionIndex][0];
                    727: 	  if (isspace(student->Answers[questionIndex][0]))
                    728: 	    total+=0;
                    729: 	  else
                    730: 	    total+=(int)(student->Answers[questionIndex][0]-'0');
                    731: 	  break;
                    732: 	case 'e':
                    733: 	  printf("%s %s\n",problems->answer,student->Answers[questionIndex]);
                    734: 	  numRight=0;
                    735: 	  for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
                    736: 	    {
                    737: 	      ansOn[leafs]=strchr(problems->answer,('A'+(char)leafs));
                    738: 	    }
                    739: 	  for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
                    740: 	    {
                    741: 	      if (ansOn[leafs] != NULL ) { ansOn[leafs]=&one;} 
                    742: 	      else { ansOn[leafs]=&zero;}
                    743: 	    }
                    744: 	  for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
                    745: 	    {
                    746: 	      stuOn[leafs]=strchr(student->Answers[questionIndex],
                    747: 				  ('A'+(char)leafs));
                    748: 	    }
                    749: 	  for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
                    750: 	    {
                    751: 	      if (stuOn[leafs] != NULL) {stuOn[leafs]=&one;} 
                    752: 	      else {stuOn[leafs]=&zero;}
                    753: 	    }
                    754: 	  for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
                    755: 	    {
                    756: 	      if (ansOn[leafs] == stuOn[leafs]) numRight++;
                    757: 	    }
                    758: 	  fprintf(stderr,"%d\n",numRight);
                    759: 	  total+=numRight;
                    760: 	  grade[questionIndex]='0'+(char)numRight;
                    761: 	  break;
                    762: 	case 'g':
                    763: 	  printf("%s %s\n",problems->answer,student->Answers[questionIndex]);
                    764: 	  if (!(strcasecmp(problems->answer,student->Answers[questionIndex])))
                    765: 	    {
                    766: 	      total+=questions[questionIndex].points;
                    767: 	      grade[questionIndex]='0'+questions[questionIndex].points;
                    768: 	    }
                    769: 	  else
                    770: 	    {
                    771: 	      grade[questionIndex]='0';
                    772: 	    }
                    773: 	  break;
                    774: 	default:
                    775: 	  printf("No points since don't know question type.\n");
                    776: 	  break;
                    777: 	}
                    778:       if (!SurveyMode) problems=problems->next;
                    779:     }
                    780: 
                    781:   answerstring[0]='\0';
                    782: 
                    783:   for(questionIndex=0;questionIndex<numQuestions;questionIndex++)
                    784:     {
                    785:       strcat(answerstring,student->Answers[questionIndex]);
                    786:     }
                    787:      
                    788:   setBubblerEntry(outputFile,student->answerPID,capaStudent.name,grade,
                    789: 		  total,capaStudent.section,answerstring,student->questionPID,
                    790: 		  offset2);
                    791: 
                    792:   if (!SurveyMode)
                    793:     {
                    794:       problems=oldproblem;
                    795:       for(questionIndex=0;problems!=NULL;questionIndex++)
                    796: 	{
                    797: 	  oldproblem=problems;
                    798: 	  problems=problems->next;
                    799: 	  free(oldproblem);
                    800: 	}
                    801: #ifdef DEBUG
                    802:       fprintf(stderr,"Freed: %d\n",questionIndex);
                    803: #endif /*DEBUG*/
                    804:     }
                    805: }
                    806: 
                    807: void processForms(FILE ** serport,int numQuestions,
                    808: 		  Question questions[MAXQUEST],char* class,int setId)
                    809: {
                    810: 
                    811:   int done=0,error,i,numOfStudents=0;
                    812:   int status;
                    813:   char buf[128],filename[128];
                    814:   Student * student;
                    815:   FILE * outputFile;
                    816:   PIDPINlist PIDandPINlist[MAX_SECTION_SIZE];
                    817: 
                    818:   sprintf(filename,"bubbler.output.%d",setId);
                    819:   outputFile=fopen(filename,"r+");
                    820:   if (outputFile != NULL)
                    821:     {
                    822:       rewind(outputFile);
                    823:       fscanf(outputFile,"%s",buf);
                    824:     }
                    825:   if (outputFile==NULL || buf[0]=='\0')
                    826:     {
                    827:       outputFile=fopen(filename,"w+");
                    828:       fprintf(outputFile,"%s %d ",class,setId);
                    829:       for(i=0;i<numQuestions;i++)
                    830: 	{
                    831: 	  fprintf(outputFile,"%c%d",questions[i].type,questions[i].points);
                    832: 	}
                    833:       fprintf(outputFile,"\n");
                    834:     }
                    835:   if (Anon)
                    836:     {
                    837:       numOfStudents=buildPIDandPINlist(setId,PIDandPINlist);
                    838:       if (numOfStudents==0)
                    839: 	{
                    840: 	  fprintf(stderr,"buildPIDandPINlists returned 0 students.");
                    841: 	  exit(-2);
                    842: 	}
                    843:     }
                    844:   
                    845:   while(!done)
                    846:     {
                    847:       student=getForm(&status,serport,questions);
                    848:       switch (status)
                    849: 	{
                    850: 	case GFSPACES:
                    851: 	  if (CheckSpaces)
                    852: 	    {
                    853: 	      printf("The current form appears to have some questions left\n");
                    854: 	      printf("blank. Please enter yes if you wish to continue \n");
                    855: 	      printf("grading of this form.\n");
                    856: 	      scanf("%s",buf);
                    857: 	      if (buf[0]=='y' || buf[0]=='Y') ;
                    858: 	      else break;
                    859: 	    }
                    860: 	case GFSUCCESS:
                    861: 	  if ((!SurveyMode) && 
                    862: 	      (error=checkForm(student,numQuestions,class,setId))) 
                    863: 	    {
                    864: 	      switch(error)
                    865: 		{
                    866: 		case ECLASS:
                    867: 		  printf("The current form has a class string that is \n");
                    868: 		  printf("different from the one entered at the start.\n");
                    869: 		  printf("Please place that form to the side and type ");
                    870: 		  printf("start to continue.\n");
                    871: 		  scanf("%s",buf);
                    872: 		  break;
                    873: 		case ESTID:
                    874: 		  printf("The current form's Student Id is incorrect.\n");
                    875: 		  printf("Please set the form aside and type start to ");
                    876: 		  printf("continue.\n");
                    877: 		  scanf("%s",buf);
                    878: 		  break;
                    879: 		case ECLASSL:
                    880: 		  fprintf(stderr,"The classl file was not found in the");
                    881: 		  fprintf(stderr," current directory.\n");
                    882: 		  fprintf(stderr,"Please try again.\n");
                    883: 		  done=1;
                    884: 		  break;
                    885: 		case EPIN:
                    886: 		  fprintf(stderr,"The current form's PIN is incorrect.\n");
                    887: 		  fprintf(stderr,"Please set the form aside and type ");
                    888: 		  fprintf(stderr,"start to continue.\n");
                    889: 		  scanf("%s",buf);
                    890: 		  break;
                    891: 		default:
                    892: 		  fprintf(stderr,"Unimplemented error in checkForm %d\n",
                    893: 			  error);
                    894: 		  break;
                    895: 		}
                    896: 	    }
                    897: 	  else
                    898: 	    {
                    899: 	      if (Anon)
                    900: 		{
                    901: 		  error=findPID(student,PIDandPINlist,numOfStudents);
                    902: 		}
                    903: 	      else
                    904: 		{
                    905: 		  error=ENONE;
                    906: 		  strcpy(student->questionPID,student->answerPID);
                    907: 		}
                    908: 	      switch(error)
                    909: 		{
                    910: 		case ENONE:
                    911: 		  writeForm(student,&outputFile,questions,numQuestions);
                    912: 		  break;
                    913: 		case ENOONE:
                    914: 		  break;
                    915: 		default:
                    916: 		  fprintf(stderr,"Unimplemented error in findPID %d\n",
                    917: 			  error);
                    918: 		  break;
                    919: 		}
                    920: 	    }
                    921: 	  break;
                    922: 	case GFFAILED:
                    923: 	  printf("The Scantron has returned an error.\n");
                    924: 	  printf("Are there still more forms to process?");
                    925: 	  scanf("%s",buf);
                    926: 	  if (buf[0]=='n')
                    927: 	    {
                    928: 	      done=1;
                    929: 	    }
                    930: 	  else
                    931: 	    {
                    932: 	      printf("Please put that last read form to the side.\n");
                    933: 	      printf("Enter start to continue\n");
                    934: 	      scanf("%s",buf);
                    935: 	    }
                    936: 	  break;
                    937: 	case GFEOF:
                    938: 	  done=1;
                    939: 	  break;
                    940: 	default:
                    941: 	  printf("Unimplened return code in GetForm %d\n",status);
                    942: 	  break;
                    943: 	}
                    944:       if (student != NULL)
                    945: 	{
                    946: 	  free(student);
                    947: 	}
                    948:     }
                    949: }
                    950: 
                    951: void CloseScantron(FILE ** serport)
                    952: {
                    953:   fprintf(*serport,".srst\r");
                    954:   fclose(*serport);
                    955: }
                    956: 
                    957: int main(int argc, char *argv[])
                    958: {
                    959:   FILE * serport;
                    960:   Question questions[MAXQUEST];
                    961:   char class[10];
                    962:   int numQuestions,setId;
                    963: 
                    964:   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");
                    965:   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");
                    966:   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");
                    967:   printf("Welcome to Bubbler, the Automated CAPA grader.\n");
                    968:   printf("Version 0.05.02\n\n\n");
                    969:   numQuestions=GetProblems(questions,class,&setId);
                    970:   SetupScantron(&serport,numQuestions,questions);
                    971:   processForms(&serport,numQuestions,questions,class,setId);
                    972:   CloseScantron(&serport);
                    973:   return 0;
                    974: }
                    975: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>