/* convert scorer.output files to set.db files Copyright (C) 1992-2000 Michigan State University The CAPA system is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The CAPA system is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the CAPA system; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, you have permission to link this program with the TtH/TtM library and distribute executables, as long as you follow the requirements of the GNU GPL in regard to all of the software in the executable aside from TtH/TtM. */ /* * scorertoset.c * Guy Albertelli II 1997 */ #include #include #include #include #include "pProj/capaCommon.h" #include "scorer.h" /**************************************************Set Database Entry */ int scorer_set_entry(ClientData notused, Tcl_Interp *interp, int argc, char** argv) { FILE *fp; int fd; int errcode=TCL_OK; int done,len,new_len,item_cnt; long next_r, orig_size, new_size, big_buf_size; char filename[FILE_NAME_LENGTH]; char *a_line, tmpline[MAX_LINE_LENGTH], errorline[MAX_LINE_LENGTH], tmp_sn[MAX_STUDENT_NUMBER+1], fmtbuf[SMALL_LINE_BUFFER]; char *big_buf; char *student_number,*answers,*tries; int set; long offset; if (argc != 6) { Tcl_SetResult(interp,"usage is: studentNumber set fileOffset answers tries", TCL_VOLATILE); return TCL_ERROR; } student_number=argv[1]; set=atoi(argv[2]); offset=atoi(argv[3]); answers=argv[4]; tries=argv[5]; offset=(offset<0)?-offset:offset; sprintf(filename,"records/set%d.sb",set); if ((fp=fopen(filename,"r+"))==NULL) { sprintf(errorline,"Error: can't open %s\n",filename); Tcl_SetResult(interp,errorline,TCL_VOLATILE); return TCL_ERROR; } a_line=capa_malloc(strlen(tries)*5+MAX_STUDENT_NUMBER,1); sprintf(a_line,"%s %s,%s\n",student_number,answers,tries); new_len = strlen(a_line); sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER); flockstream(fp); fseek(fp,0L,SEEK_END); orig_size = ftell(fp); big_buf_size = orig_size + new_len; big_buf = capa_malloc(big_buf_size,1); fseek(fp,0L,SEEK_SET); /* rewind to beginning of file */ fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* skip weight line, including \n */ fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* hand grading */ done = 0; while(!done) { done = !fgets(tmpline,TMP_LINE_LENGTH-1,fp); len = strlen(tmpline); if( !done ) { sscanf(tmpline,fmtbuf,tmp_sn); if( !strncasecmp(tmp_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */ next_r = ftell(fp); offset = next_r - len; done = 1; item_cnt=fread(big_buf,1,big_buf_size, fp); /* read remaining lines into buffer */ if(item_cnt >= 0 ) { /* no error reading remaining lines */ big_buf[item_cnt]=0; /* terminate the buffer, for sure */ fseek(fp,offset,SEEK_SET); /* reposition file pointer to the record */ if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */ sprintf(errorline,"Error writing data to file: %s\n",filename); Tcl_SetResult(interp,errorline,TCL_VOLATILE); errcode= TCL_ERROR; } if (item_cnt != 0) { if (!fwrite(big_buf,item_cnt,1,fp) ){/*write out the remainings*/ sprintf(errorline,"Error writing data to file: %s\n",filename); Tcl_SetResult(interp,errorline,TCL_VOLATILE); errcode= TCL_ERROR; } } new_size = ftell(fp); if(new_size < orig_size ) { fd = fileno(fp); ftruncate(fd,new_size); } } } } else { /* end of file */ fseek(fp,0L,SEEK_END); offset = ftell(fp); /* last byte, if last byte is cr, back up one */ fseek(fp,-1L,SEEK_END); while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); } offset = offset +2; /* last char and cr */ done=1; fseek(fp,offset,SEEK_SET); if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */ sprintf(errorline,"Error writing data to file: %s\n",filename); Tcl_SetResult(interp,errorline,TCL_VOLATILE); errcode= TCL_ERROR; } } } fflush(fp); funlockstream(fp); /* <======= unlock the file */ fclose(fp); capa_mfree(big_buf); /* free up the buffer */ return (errcode); } /**************************************************** Get db entry*/ /* RETURNS: byte offset to start of record, 0 if error, -offset if not found & newly created */ int scorer_get_entry(ClientData notused, Tcl_Interp *interp, int argc, char** argv) { char filename[FILE_NAME_LENGTH]; FILE *fp; int len, nq; char *ans_p, *tries_p,oneline[MAX_LINE_LENGTH],fmtbuf[MAX_LINE_LENGTH], buf[MAX_LINE_LENGTH]; long offset=0, next_r; int ii, done, found=0,set; char a_sn[MAX_STUDENT_NUMBER+1]; char *student_number; T_entry *entry; if (argc!=3) { Tcl_SetResult(interp,"usage is: studentNumber set",TCL_VOLATILE); return TCL_ERROR; } set=atoi(argv[2]); student_number=argv[1]; entry=(T_entry*)capa_malloc(1,sizeof(T_entry)); sprintf(filename,"records/set%d.sb",set); if ((fp=fopen(filename,"r"))==NULL) { sprintf(buf,"Error: can't open %s\n",filename); Tcl_SetResult(interp,buf,TCL_VOLATILE); return TCL_ERROR; } sprintf(entry->student_number,"%s",student_number); sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER); flockstream(fp); fgets(oneline,MAX_LINE_LENGTH-1,fp); len = strlen(oneline); sscanf(oneline,"%d",&nq); ans_p = capa_malloc(nq+1,1); tries_p = capa_malloc(3*nq,1); fgets(oneline,MAX_LINE_LENGTH-1,fp); /* skip weight line */ fgets(oneline,MAX_LINE_LENGTH-1,fp); /* hand grading */ done = 0; while(!done) { done = !fgets(oneline,MAX_LINE_LENGTH-1,fp); len = strlen(oneline); if( !done ) { sscanf(oneline,fmtbuf,a_sn); if( !strncasecmp(a_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */ next_r = ftell(fp); offset = next_r - len; done = 1; found = 1; } } else { fseek(fp,0L,SEEK_END); offset = ftell(fp); /* last byte, if last bye is cr, back up one */ fseek(fp,-1L,SEEK_END); while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); } offset = offset +2; /* last char and cr */ found = 0; done=1; } } funlockstream(fp); fclose(fp); if(!found) { for(ii=0;iianswers = ans_p; entry->tries = tries_p; entry->e_probs = nq; /*if (scorer_set_entry(entry,student_number,set,offset)==-1) offset=0;*/ offset = -offset; } else { sprintf(fmtbuf, "%%%dc",nq); sscanf(oneline + MAX_STUDENT_NUMBER+1,fmtbuf,ans_p); sprintf(fmtbuf, "%%%dc",(3*nq-1)); sscanf(oneline + MAX_STUDENT_NUMBER+1+nq+1,fmtbuf,tries_p); entry->answers = ans_p; entry->tries = tries_p; entry->e_probs = nq; } sprintf(buf,"%ld;%d;%s;%s",offset,entry->e_probs,entry->answers,entry->tries); Tcl_SetResult(interp,buf,TCL_VOLATILE); return TCL_OK; } void processFile(FILE *inputFile,Question questions[MAX_QUEST],int setId, int gradingMethod,int numQuestions) { T_entry grade; char studentNumber[MAX_STUDENT_NUMBER+1],name[MAX_NAME_CHAR+1]; int score,section,buf,i,numRight,points=0,leafs,processed=0,unit; printf("Processing"); while(fscanf(inputFile,"%s",studentNumber)!=EOF) { processed++; if (processed%100==1) { printf("%d",processed-1); } printf("."); fflush(stdout); /* if ((offset = scorer_get_entry(&grade,studentNumber,setId))==0) { fprintf(stderr,"Please create the set%d.sb file\n",setId); exit(-1); } */ fscanf(inputFile,"%30c",name); fscanf(inputFile,"%s",grade.answers); fscanf(inputFile,"%d",&score); fscanf(inputFile,"%d",§ion); if ( (grade.e_probs != strlen(grade.answers)) || (strlen(grade.answers) != numQuestions)) { fprintf(stderr,"There is a disagreement in the number of problems"); fprintf(stderr,"\nNumQuestions:%d\n",numQuestions); fprintf(stderr,"strlen(grade.answers):%d\n",strlen(grade.answers)); fprintf(stderr,"grade.answers:%s\n",grade.answers); fprintf(stderr,"grade.e_probs:%d\n",grade.e_probs); fprintf(stderr,"The set.sb file may have bad entries, please\n"); fprintf(stderr,"check the file and fix the error.\n"); exit(-1); } buf='\0'; while(buf!='\n') { buf=fgetc(inputFile); } #ifdef DEBUG printf("%d %d\n",numQuestions,strlen(grade.answers)); #endif /*DEBUG*/ for(i=0;i