1: /* convert scorer.output files to set.db files
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: * scorertoset.c
27: * Guy Albertelli II 1997
28: */
29: #include <stdio.h>
30: #include <ctype.h>
31: #include <tcl.h>
32: #include <tk.h>
33: #include "pProj/capaCommon.h"
34: #include "scorer.h"
35:
36: /**************************************************Set Database Entry */
37: int scorer_set_entry(ClientData notused, Tcl_Interp *interp, int argc, char** argv)
38: {
39: FILE *fp;
40: int fd;
41: int errcode=TCL_OK;
42: int done,len,new_len,item_cnt;
43: long next_r, orig_size, new_size, big_buf_size;
44: char filename[FILE_NAME_LENGTH];
45: char *a_line, tmpline[MAX_LINE_LENGTH], errorline[MAX_LINE_LENGTH],
46: tmp_sn[MAX_STUDENT_NUMBER+1], fmtbuf[SMALL_LINE_BUFFER];
47: char *big_buf;
48: char *student_number,*answers,*tries;
49: int set;
50: long offset;
51:
52: if (argc != 6) {
53: Tcl_SetResult(interp,"usage is: studentNumber set fileOffset answers tries",
54: TCL_VOLATILE);
55: return TCL_ERROR;
56: }
57: student_number=argv[1];
58: set=atoi(argv[2]);
59: offset=atoi(argv[3]);
60: answers=argv[4];
61: tries=argv[5];
62:
63: offset=(offset<0)?-offset:offset;
64:
65: sprintf(filename,"records/set%d.sb",set);
66: if ((fp=fopen(filename,"r+"))==NULL) {
67: sprintf(errorline,"Error: can't open %s\n",filename);
68: Tcl_SetResult(interp,errorline,TCL_VOLATILE);
69: return TCL_ERROR;
70: }
71: a_line=capa_malloc(strlen(tries)*5,1);
72: sprintf(a_line,"%s %s,%s\n",student_number,answers,tries);
73: new_len = strlen(a_line);
74: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
75: flockstream(fp);
76: fseek(fp,0L,SEEK_END);
77: orig_size = ftell(fp);
78: big_buf_size = orig_size + new_len;
79: big_buf = capa_malloc(big_buf_size,1);
80: fseek(fp,0L,SEEK_SET); /* rewind to beginning of file */
81: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* skip weight line, including \n */
82: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* hand grading */
83: done = 0;
84: while(!done) {
85: done = !fgets(tmpline,TMP_LINE_LENGTH-1,fp); len = strlen(tmpline);
86: if( !done ) {
87: sscanf(tmpline,fmtbuf,tmp_sn);
88: if( !strncasecmp(tmp_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
89: next_r = ftell(fp); offset = next_r - len; done = 1;
90: item_cnt=fread(big_buf,1,big_buf_size, fp); /* read remaining lines into buffer */
91: if(item_cnt >= 0 ) { /* no error reading remaining lines */
92: big_buf[item_cnt]=0; /* terminate the buffer, for sure */
93: fseek(fp,offset,SEEK_SET); /* reposition file pointer to the record */
94: if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */
95: sprintf(errorline,"Error writing data to file: %s\n",filename);
96: Tcl_SetResult(interp,errorline,TCL_VOLATILE);
97: errcode= TCL_ERROR;
98: }
99: if (item_cnt != 0) {
100: if (!fwrite(big_buf,item_cnt,1,fp) ){/*write out the remainings*/
101: sprintf(errorline,"Error writing data to file: %s\n",filename);
102: Tcl_SetResult(interp,errorline,TCL_VOLATILE);
103: errcode= TCL_ERROR;
104: }
105: }
106: new_size = ftell(fp);
107: if(new_size < orig_size ) {
108: fd = fileno(fp);
109: ftruncate(fd,new_size);
110: }
111: }
112: }
113: } else { /* end of file */
114: fseek(fp,0L,SEEK_END);
115: offset = ftell(fp); /* last byte, if last byte is cr, back up one */
116: fseek(fp,-1L,SEEK_END);
117: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
118: offset = offset +2; /* last char and cr */
119: done=1;
120: fseek(fp,offset,SEEK_SET);
121: if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */
122: sprintf(errorline,"Error writing data to file: %s\n",filename);
123: Tcl_SetResult(interp,errorline,TCL_VOLATILE);
124: errcode= TCL_ERROR;
125: }
126: }
127: }
128: fflush(fp);
129: funlockstream(fp); /* <======= unlock the file */
130: fclose(fp);
131: capa_mfree(big_buf); /* free up the buffer */
132: return (errcode);
133: }
134:
135: /**************************************************** Get db entry*/
136: /* RETURNS: byte offset to start of record, 0 if error,
137: -offset if not found & newly created
138:
139: */
140: int scorer_get_entry(ClientData notused, Tcl_Interp *interp, int argc, char** argv)
141: {
142: char filename[FILE_NAME_LENGTH];
143: FILE *fp;
144: int len, nq;
145: char *ans_p, *tries_p,oneline[MAX_LINE_LENGTH],fmtbuf[MAX_LINE_LENGTH],
146: buf[MAX_LINE_LENGTH];
147: long offset=0, next_r;
148: int ii, done, found=0,set;
149: char a_sn[MAX_STUDENT_NUMBER+1];
150: char *student_number;
151: T_entry *entry;
152:
153: if (argc!=3) {
154: Tcl_SetResult(interp,"usage is: studentNumber set",TCL_VOLATILE);
155: return TCL_ERROR;
156: }
157: set=atoi(argv[2]);
158: student_number=argv[1];
159: entry=(T_entry*)capa_malloc(1,sizeof(T_entry));
160:
161: sprintf(filename,"records/set%d.sb",set);
162: if ((fp=fopen(filename,"r"))==NULL) {
163: sprintf(buf,"Error: can't open %s\n",filename);
164: Tcl_SetResult(interp,buf,TCL_VOLATILE);
165: return TCL_ERROR;
166: }
167: sprintf(entry->student_number,"%s",student_number);
168: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
169: flockstream(fp);
170: fgets(oneline,MAX_LINE_LENGTH-1,fp);
171: len = strlen(oneline); sscanf(oneline,"%d",&nq);
172: ans_p = capa_malloc(nq+1,1); tries_p = capa_malloc(3*nq,1);
173: fgets(oneline,MAX_LINE_LENGTH-1,fp); /* skip weight line */
174: fgets(oneline,MAX_LINE_LENGTH-1,fp); /* hand grading */
175: done = 0;
176: while(!done) {
177: done = !fgets(oneline,MAX_LINE_LENGTH-1,fp); len = strlen(oneline);
178: if( !done ) {
179: sscanf(oneline,fmtbuf,a_sn);
180: if( !strncasecmp(a_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
181: next_r = ftell(fp); offset = next_r - len; done = 1; found = 1;
182: }
183: } else {
184: fseek(fp,0L,SEEK_END);
185: offset = ftell(fp); /* last byte, if last bye is cr, back up one */
186: fseek(fp,-1L,SEEK_END);
187: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
188: offset = offset +2; /* last char and cr */
189: found = 0; done=1;
190: }
191: }
192: funlockstream(fp); fclose(fp);
193: if(!found) {
194: for(ii=0;ii<nq;ii++) { /* Initialize answer string and tries string */
195: ans_p[ii] = '-'; tries_p[3*ii] = ' '; tries_p[3*ii + 1] = '0';
196: if(ii < nq-1) tries_p[3*ii + 2] = ',';
197: }
198: entry->answers = ans_p;
199: entry->tries = tries_p;
200: entry->e_probs = nq;
201: /*if (scorer_set_entry(entry,student_number,set,offset)==-1)
202: offset=0;*/
203: offset = -offset;
204: } else {
205: sprintf(fmtbuf, "%%%dc",nq);
206: sscanf(oneline + MAX_STUDENT_NUMBER+1,fmtbuf,ans_p);
207: sprintf(fmtbuf, "%%%dc",(3*nq-1));
208: sscanf(oneline + MAX_STUDENT_NUMBER+1+nq+1,fmtbuf,tries_p);
209: entry->answers = ans_p;
210: entry->tries = tries_p;
211: entry->e_probs = nq;
212: }
213: sprintf(buf,"%d;%d;%s;%s",offset,entry->e_probs,entry->answers,entry->tries);
214: Tcl_SetResult(interp,buf,TCL_VOLATILE);
215: return TCL_OK;
216: }
217:
218: void processFile(FILE *inputFile,Question questions[MAX_QUEST],int setId,
219: int gradingMethod,int numQuestions)
220: {
221: T_entry grade;
222: char studentNumber[MAX_STUDENT_NUMBER+1],name[MAX_NAME_CHAR+1];
223: int offset,score,section,buf,i,numRight,points=0,leafs,processed=0,unit;
224:
225: printf("Processing");
226: while(fscanf(inputFile,"%s",studentNumber)!=EOF)
227: {
228: processed++;
229: if (processed%100==1) { printf("%d",processed-1); }
230: printf(".");
231: fflush(stdout);
232: /* if ((offset = scorer_get_entry(&grade,studentNumber,setId))==0)
233: {
234: fprintf(stderr,"Please create the set%d.sb file\n",setId);
235: exit(-1);
236: }
237: */
238: fscanf(inputFile,"%30c",name);
239: fscanf(inputFile,"%s",grade.answers);
240: fscanf(inputFile,"%d",&score);
241: fscanf(inputFile,"%d",§ion);
242: if ( (grade.e_probs != strlen(grade.answers))
243: ||
244: (strlen(grade.answers) != numQuestions))
245: {
246: fprintf(stderr,"There is a disagreement in the number of problems");
247: fprintf(stderr,"\nNumQuestions:%d\n",numQuestions);
248: fprintf(stderr,"strlen(grade.answers):%d\n",strlen(grade.answers));
249: fprintf(stderr,"grade.answers:%s\n",grade.answers);
250: fprintf(stderr,"grade.e_probs:%d\n",grade.e_probs);
251: fprintf(stderr,"The set.sb file may have bad entries, please\n");
252: fprintf(stderr,"check the file and fix the error.\n");
253: exit(-1);
254: }
255: buf='\0';
256: while(buf!='\n')
257: {
258: buf=fgetc(inputFile);
259: }
260: #ifdef DEBUG
261: printf("%d %d\n",numQuestions,strlen(grade.answers));
262: #endif /*DEBUG*/
263: for(i=0;i<numQuestions;i++)
264: {
265: switch(questions[i].type)
266: {
267: case ONE_OUT_OF_8:
268: case SINGLE_DIGIT:
269: numRight= (int) (grade.answers[i]-'0');
270: score=numRight*questions[i].points;
271: grade.answers[i]='0'+(char)score;
272: break;
273: case STRING_MATCH:
274: /*for STRING_MATCH the score is stroed as the NumRight*/
275: numRight= (int) (grade.answers[i]-'0');
276: score=numRight;
277: grade.answers[i]='0'+(char)score;
278: break;
279: case GLE:
280: case TF:
281: case N_OUT_OF_M:
282: numRight=(int) (grade.answers[i]-'0');
283: leafs=questions[i].leafs;
284: points=questions[i].points;
285: unit=(int)ceil((double)points/(double)leafs);
286: if (unit==0) unit=points;
287: switch (gradingMethod)
288: {
289: case CAPA_METHOD:
290: score=points-(2*unit*(leafs-numRight));
291: break;
292: case LENIENT_METHOD:
293: score=points-(unit*(leafs-numRight));
294: break;
295: case STRICT:
296: if (numRight==leafs) score=points;
297: else score=0;
298: break;
299: default:
300: fprintf(stderr,"Unknown grading Method. %d\n",gradingMethod);
301: break;
302: }
303: if (score<0)
304: score=0;
305: grade.answers[i]='0'+(char)score;
306: break;
307: case ASSIGNED:
308: /*
309: *grade.answers already has the correct number of points.
310: *i.e whatever the scorer.output file had in it and was put in
311: *grade.
312: */
313: break;
314: default:
315: fprintf(stderr,"Unknown question type %c\n",questions[i].type);
316: break;
317: }
318: }
319: for(i=0;i<strlen(grade.answers);i++)
320: {
321: grade.tries[3*i]=' ';
322: grade.tries[3*i+1]='1';
323: grade.tries[3*i+2]=',';
324: }
325: grade.tries[3*i-1]='\0';
326: grade.answers[i]='\0';
327: #ifdef DEBUG
328: printf("%s\n",studentNumber);
329: #endif /*DEBUG*/
330: /*if (scorer_set_entry(&grade,studentNumber,setId,abs(offset))==-1)
331: {
332: fprintf(stderr,"Please create the set%d.sb file\n",setId);
333: exit(-1);
334: }
335: */
336: }
337: printf("\nProcessed %d results\n",processed);
338: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>