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>