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