1: /*
2: * scorer.c
3: * Copyright Guy Albertelli II 1997
4: */
5: #include <stdio.h>
6: #include <stdlib.h>
7: #include <ctype.h>
8: #include <string.h>
9: #ifdef NeXT
10: #endif
11: #ifdef linux
12: #include <sys/types.h>
13: #include <sys/stat.h>
14: #include <fcntl.h>
15: #include <termios.h>
16: #include <unistd.h>
17: #endif
18: #include <tcl.h>
19: #include <tk.h>
20: #include "Capa/capaCommon.h"
21: #include "scorer.h"
22: #include "manager.h"
23: #ifdef DMALLOC
24: #include <dmalloc.h>
25: #endif
26:
27: extern int Parsemode_f;
28: char NUMBER[10]={'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
29: char LETTER[10]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};
30: PIDPINlist *studentList;
31:
32: /* 2 arguments, string 1 and string 2 result is an integer of # charactes the same*/
33: int compareCapaID(ClientData notused, Tcl_Interp *interp, int argc,
34: char* argv[])
35: {
36: int same=0,length,i;
37: char buf[MAX_BUFFER_SIZE];
38: length=strlen(argv[1]);
39: for(i=0;i<length;i++) if(argv[1][i] == argv[2][i]) same++;
40: sprintf(buf,"%d",same);
41: Tcl_SetResult(interp,buf,TCL_VOLATILE);
42: return TCL_OK;
43: }
44:
45: /* 3 arguments, the PID of the student, the setID, the number of expected questions */
46: int getAnswersFromSet(ClientData notused, Tcl_Interp *interp, int argc,
47: char* argv[])
48: {
49: int result,capaQuestions,questionIndex,numRight,total=0,numQuestions;
50: Problem_t *curProblem,*headProblem;
51: char answerstring[MAX_LINE_LENGTH],grade[MAX_LINE_LENGTH];
52: char *buf;
53: T_student capaStudent;
54: char* questionPID;
55: int setID;
56: Tcl_Obj* tclResult;
57:
58:
59: if (argc!=4) {
60: Tcl_SetResult(interp,"usage is: PID setID numQuestions",TCL_VOLATILE);
61: return TCL_ERROR;
62: }
63: questionPID=argv[1];
64: setID=atoi(argv[2]);
65: numQuestions=atoi(argv[3]);
66:
67: result=capa_parse(setID,&headProblem,questionPID,&capaQuestions,NULL);
68: curProblem=headProblem;
69:
70: if (result==0 || result == -1) {
71: buf=capa_malloc(MAX_LINE_LENGTH,sizeof(char));
72: sprintf(buf,"The Parse failed: %d\n",result);
73: Tcl_SetResult(interp,buf,TCL_VOLATILE);
74: capa_mfree(buf);
75: return TCL_ERROR;
76: } else if (result != numQuestions) {
77: buf=capa_malloc(MAX_LINE_LENGTH,sizeof(char));
78: sprintf(buf,"The parser found %d questions, there were supposed to be %d questions.\nDying\n",result,numQuestions);
79: Tcl_SetResult(interp,buf,TCL_VOLATILE);
80: capa_mfree(buf);
81: return TCL_ERROR;
82: }
83:
84: tclResult=Tcl_NewStringObj("",0);
85: Tcl_IncrRefCount(tclResult);
86: for(questionIndex=0;questionIndex<numQuestions;questionIndex++) {
87: buf=(char*)capa_malloc(strlen(curProblem->answer)+MAX_LINE_LENGTH,sizeof(char));
88: sprintf(buf,"%s ",curProblem->answer);
89: Tcl_AppendStringsToObj(tclResult,buf,NULL);
90: capa_mfree(buf);
91: curProblem=curProblem->next;
92: }
93: free_problems(headProblem);
94: Tcl_SetObjResult(interp,tclResult);
95: Tcl_DecrRefCount(tclResult);
96: return TCL_OK;
97: }
98:
99: /*needs num (the unique ident)*/
100: int freeStudentList(ClientData notused, Tcl_Interp *interp, int agrc,
101: char* argv[])
102: {
103: int i,num = atoi(argv[1]);
104: PIDPINlist *cur,*prev;
105:
106: if (!studentList) { return TCL_OK; }
107:
108: cur=studentList;
109: prev=NULL;
110: while((cur->num!=num) && cur->next) { prev=cur; cur=cur->next; }
111: if (cur->num!=num) { return TCL_OK; }
112:
113: capa_mfree(cur->classname);
114: for(i=0;i<cur->numStudents;i++) capa_mfree(cur->classList[i].capaid_plus);
115: capa_mfree((char*)cur->classList);
116: if ( prev != NULL ) {
117: prev->next=cur->next;
118: } else {
119: if (cur->next) studentList=cur->next;
120: }
121: capa_mfree((char*)cur);
122: return TCL_OK;
123: }
124:
125: /*needs num (unique ident), classname, setId, capaid_plus size*/
126: int buildStudentList(ClientData notused, Tcl_Interp *interp, int argc,
127: char* argv[])
128: {
129: long i,j,numStudents,num,capaidplusSize,setId,part1,part2;
130: T_student *curStudent,*headStudent;
131: PIDPINlist *cur;
132: char *buf,*buf2;
133: Tcl_Obj* tclResult;
134:
135: if (argc!=5) {
136: Tcl_SetResult(interp,"usage is: number classname setId capa_id_plus_size",
137: TCL_VOLATILE);
138: return TCL_ERROR;
139: }
140:
141: if (studentList) {
142: cur=studentList;
143: while(cur->next) { cur=cur->next; }
144: cur->next=(PIDPINlist*)capa_malloc(1,sizeof(PIDPINlist));
145: cur=cur->next;
146: } else {
147: studentList=(PIDPINlist*)capa_malloc(1,sizeof(PIDPINlist));
148: cur=studentList;
149: }
150: cur->classname=(char*)capa_malloc(strlen(argv[2]),sizeof(char));
151: strcpy(argv[2],cur->classname);
152: cur->num=num=atoi(argv[1]);
153: setId=atoi(argv[3]);
154: capaidplusSize=atoi(argv[4]);
155:
156: numStudents=capa_get_section(&headStudent, 0);
157: if ( numStudents == 0 ) {
158: Tcl_SetResult(interp,"No students in class.",TCL_VOLATILE);
159: return TCL_ERROR;
160: } else if ( numStudents < 0 ) {
161: Tcl_SetResult(interp,"Unable to read the classl file",TCL_VOLATILE);
162: return TCL_ERROR;
163: }
164: cur->classList=(PIDPIN*)capa_malloc(numStudents,sizeof(PIDPIN));
165: curStudent=headStudent;
166: tclResult=Tcl_NewStringObj("",0);
167: Tcl_IncrRefCount(tclResult);
168: for(i=0;curStudent;curStudent=curStudent->s_next,i++) {
169: capa_seed(&part1, &part2, curStudent->s_sn);setall(part1, part2);
170: strcpy(cur->classList[i].PID,curStudent->s_sn);
171: cur->classList[i].PIN=capa_PIN(curStudent->s_sn,setId,0);
172: cur->classList[i].capaid_plus=capa_id_plus(curStudent->s_sn,setId,capaidplusSize);
173: j=strlen(cur->classList[i].capaid_plus)+MAX_PIN_CHAR+
174: strlen(cur->classList[i].PID)+strlen(curStudent->s_nm)+MAX_LINE_LENGTH;
175: buf=(char*)capa_malloc(j,sizeof(char));
176: sprintf(buf,"{{%s} %s %d %s} ",curStudent->s_nm,curStudent->s_sn,
177: cur->classList[i].PIN,cur->classList[i].capaid_plus);
178: Tcl_AppendStringsToObj(tclResult,buf,NULL);
179: capa_mfree(buf);
180: }
181: Tcl_SetObjResult(interp,tclResult);
182: Tcl_IncrRefCount(tclResult);
183: free_students(headStudent);
184: cur->numStudents=numStudents;
185: return TCL_OK;
186: }
187:
188: int gradeQuestion(Question questions[MAX_QUEST],int questionIndex,
189: Problem_t *problem,Student *student,Flags* flags)
190: {
191: int numRight=0,leafs;
192: char one=1,zero=0;
193: char *ansOn[20],*stuOn[20];
194: int i,j;
195: int sortArray[256];
196: char newAnswer[MAX_LINE_LENGTH],*oldAnswer;
197:
198: switch(questions[questionIndex].type)
199: {
200: case ONE_OUT_OF_8:
201: case GLE:
202: case TF:
203: case SINGLE_DIGIT:
204: if (!flags->log)
205: printf("The correct answer:%10s The student's answer:%10s, \t",
206: problem->answer,student->Answers[questionIndex]);
207: for(leafs=0;problem->answer[leafs]!='\0';leafs++)
208: if (problem->answer[leafs]==student->Answers[questionIndex][leafs])
209: numRight++;
210: if (!flags->log)
211: printf("%d right\n",numRight);
212: break;
213: case ASSIGNED:
214: if (!flags->log)
215: printf("The student got a %s out of %d\n",
216: student->Answers[questionIndex],
217: questions[questionIndex].points);
218: if (isspace(student->Answers[questionIndex][0]))
219: numRight=0;
220: else
221: numRight=(int)(student->Answers[questionIndex][0]-'0');
222: break;
223: case N_OUT_OF_M:
224: if (!flags->log)
225: printf("The correct answer:%10s The student's answer:%10s, \t",
226: problem->answer,student->Answers[questionIndex]);
227: if (problem->ans_type == ANSWER_IS_CHOICE) {
228: for(i=0;i<255;i++) sortArray[i]=0;
229: for(i=0;i< strlen(problem->answer);i++)
230: sortArray[(int)problem->answer[i]]=1;
231: for(i=0,j=0;i<255;i++) {
232: if (sortArray[i]) {
233: newAnswer[j]=i;
234: j++;
235: }
236: }
237: newAnswer[j]='\0';
238: if (!flags->log)
239: printf("\nThe sorted correct answer:%10s\t\t\t",newAnswer);
240: oldAnswer=problem->answer;
241: problem->answer=newAnswer;
242: }
243: for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
244: {
245: ansOn[leafs]=strchr(problem->answer,('A'+(char)leafs));
246: }
247: for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
248: {
249: if (ansOn[leafs] != NULL )
250: ansOn[leafs]=&one;
251: else
252: ansOn[leafs]=&zero;
253: }
254: for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
255: {
256: stuOn[leafs]=strchr(student->Answers[questionIndex],
257: ('A'+(char)leafs));
258: }
259: for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
260: {
261: if (stuOn[leafs] != NULL)
262: stuOn[leafs]=&one;
263: else
264: stuOn[leafs]=&zero;
265: }
266: for(leafs=0;questions[questionIndex].leafs>leafs;leafs++)
267: if (ansOn[leafs] == stuOn[leafs])
268: numRight++;
269: if (!flags->log)
270: printf("%d right\n",numRight);
271: if (problem->ans_type == ANSWER_IS_CHOICE) problem->answer=oldAnswer;
272: break;
273: case STRING_MATCH:
274: if (!flags->log)
275: printf("The correct answer:%10s The student's answer:%10s, ",
276: problem->answer,student->Answers[questionIndex]);
277: if (problem->ans_type == ANSWER_IS_CHOICE) {
278: for(i=0;i<255;i++) sortArray[i]=0;
279: for(i=0;i< strlen(problem->answer);i++)
280: sortArray[(int)problem->answer[i]]=1;
281: for(i=0,j=0;i<255;i++) {
282: if (sortArray[i]) {
283: newAnswer[j]=i;
284: j++;
285: }
286: }
287: newAnswer[j]='\0';
288: if (!flags->log)
289: printf("\nThe sorted correct answer:%10s\t\t\t",newAnswer);
290: oldAnswer=problem->answer;
291: problem->answer=newAnswer;
292: }
293: if (!(strcasecmp(problem->answer,student->Answers[questionIndex]))) {
294: if (!flags->log) printf("Answer is correct\n");
295: numRight=questions[questionIndex].points;
296: } else {
297: if (!flags->log) printf("Answer is wrong\n");
298: numRight=0;
299: }
300: if (problem->ans_type == ANSWER_IS_CHOICE) problem->answer=oldAnswer;
301: break;
302: default:
303: fprintf(stderr,"Unknown question type while grading, %c.\nDying.\n",
304: questions[questionIndex].type);
305: exit(E_UNKNOWN_QTYPE);
306: break;
307: }
308: return numRight;
309: }
310:
311:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>