/* interfaces to the C portions of CAPA for grader 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. */ /* * grader.funct.c * Guy Albertelli II 1996 */ #include #include #include #include #include #include #include /* * used to remeber the weights and partial credit from a parse for when * setting a DBHeader */ /* Reads a header form the file and sets up the time and date variables */ int capaGetHeader(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { T_header header; char * setNumber,buf[BUFFER_SIZE],*sectionNumber,dateStr[BUFFER_SIZE]; int set,section,result; setNumber=Tcl_GetVar(interp,"gSetLoad",TCL_GLOBAL_ONLY); sectionNumber=Tcl_GetVar(interp,"gSectionLoad",TCL_GLOBAL_ONLY); if ( setNumber[0] == '\0' ) return TCL_OK; if ( sectionNumber[0] == '\0' ) return TCL_OK; set=atoi(setNumber); section=atoi(sectionNumber); result=capa_get_header(&header,set); if ( result == -1 ) { Tcl_ResetResult(interp); Tcl_AppendElement(interp,"0"); return TCL_OK; } result=capa_get_date(CHECK_OPEN_DATE,NULL,section,set,dateStr); if (result<0) { Tcl_ResetResult(interp); Tcl_AppendElement(interp,"-1"); return TCL_OK; } sscanf(dateStr,"%10c",buf); buf[10]='\0'; Tcl_SetVar(interp,"gOpenDate",buf,TCL_GLOBAL_ONLY); sscanf((dateStr)+11,"%5c",buf); buf[5]='\0'; Tcl_SetVar(interp,"gOpenTime",buf,TCL_GLOBAL_ONLY); result=capa_get_date(CHECK_DUE_DATE,NULL,section,set,dateStr); if (result<0) { Tcl_ResetResult(interp); Tcl_AppendElement(interp,"-1"); return TCL_OK; } sscanf(dateStr,"%10c",buf); buf[10]='\0'; Tcl_SetVar(interp,"gDueDate",buf,TCL_GLOBAL_ONLY); sscanf((dateStr)+11,"%5c",buf); buf[5]='\0'; Tcl_SetVar(interp,"gDueTime",buf,TCL_GLOBAL_ONLY); result=capa_get_date(CHECK_ANS_DATE,NULL,section,set,dateStr); if (result<0) { Tcl_ResetResult(interp); Tcl_AppendElement(interp,"-1"); return TCL_OK; } sscanf(dateStr,"%10c",buf); buf[10]='\0'; Tcl_SetVar(interp,"gAnswerDate",buf,TCL_GLOBAL_ONLY); sscanf((dateStr)+11,"%5c",buf); buf[5]='\0'; Tcl_SetVar(interp,"gAnswerTime",buf,TCL_GLOBAL_ONLY); Tcl_ResetResult(interp); Tcl_AppendElement(interp,"1"); capa_mfree(header.weight); capa_mfree(header.partial_credit); return TCL_OK; } /* get the information for all of the students in the current section * and puts them into the listbox. * Arguments: the name of the variable the widget name of the listbox * is in. */ int capaGetStudents(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { T_student *headStudent,*currentStudent; int result,section,set,setScore,maxScore,num=0; char buf[BUFFER_SIZE],buf2[BUFFER_SIZE],*answers,*listWidget; section=atoi(Tcl_GetVar(interp,"gSectionLoad",TCL_GLOBAL_ONLY)); set=atoi(Tcl_GetVar(interp,"gSetLoad",TCL_GLOBAL_ONLY)); if ( (listWidget = Tcl_GetVar(interp,argv[1], TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)) == NULL) { fprintf(stderr,"Tcl_GetVar error\n"); fprintf(stderr,"%s\n",interp->result); return TCL_ERROR; } result=capa_sorted_section(&headStudent,section); if (result == -1 || result == 0) { Tcl_Eval(interp,"displayError \"Invalid section\""); Tcl_ResetResult(interp); return TCL_OK; } currentStudent=headStudent; while(currentStudent!=NULL) { num++; setScore = capa_get_score(currentStudent->s_sn,set,&maxScore,&answers); if ( setScore == -1 ) setScore=0; sprintf(buf,"%s %s %2d/%2d %2d ",currentStudent->s_nm, currentStudent->s_sn,setScore,maxScore, capa_PIN(currentStudent->s_sn,set,0)); capaPrepareBuffer(buf,buf2,0); sprintf(buf,"%s insert end \"%s\" ",listWidget,buf2); if (Tcl_Eval(interp,buf) != TCL_OK) { fprintf(stderr,"Tcl_Eval error\n"); fprintf(stderr,"%s\n",interp->result); free_students(headStudent); return TCL_ERROR; } if (!(num%10)) { if (Tcl_Eval(interp,"update") != TCL_OK) { fprintf(stderr,"Tcl_Eval error\n"); fprintf(stderr,"%s\n",interp->result); free_students(headStudent); return TCL_ERROR; } } currentStudent=currentStudent->s_next; capa_mfree(answers); } free_students(headStudent); if (!(num%5)) { if (Tcl_Eval(interp,"update") != TCL_OK) { fprintf(stderr,"Tcl_Eval error\n"); fprintf(stderr,"%s\n",interp->result); return TCL_ERROR; } } return TCL_OK; } /* searches for the section a student is in by either name or number * Arguments: one of (name or number) and then the name or number to * search for. */ int capaFindSection(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { int errorNm; char searchStr[MAX_NAME_CHAR+1],buf[MAX_NAME_CHAR+1]; T_student student; switch(argv[1][1]) { case 'a': strncpy(searchStr,argv[2],MAX_NAME_CHAR+1); if ( (errorNm = capa_student_byname(searchStr,&student ))==0 ) { sprintf(buf,"%d",0); } else { sprintf(buf,"%d",student.s_sec); } break; case 'u': strncpy(searchStr,argv[2],MAX_NAME_CHAR+1); if ( (errorNm = capa_get_student(searchStr,&student ))==0 ) { sprintf(buf,"%d",0); } else { sprintf(buf,"%d",student.s_sec); } break; default: break; } Tcl_ResetResult(interp); Tcl_AppendElement(interp,buf); return TCL_OK; } /* makes a student report * Arguments: the student number */ int capaGetReportInfo(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { char studentNumber[MAX_STUDENT_NUMBER+1], lineOne[BUFFER_SIZE],*wgt,*partialCredit; T_header header; T_entry entry; int ii, setIdx, setScores, setValids, totalSet, totalProbs, neverLogin; int termScores, termValids; strncpy(studentNumber,argv[1], MAX_STUDENT_NUMBER+1); totalSet = howManySetDBFile(); Tcl_ResetResult(interp); for(termScores=0,termValids=0,setIdx=1;setIdx <= totalSet ;setIdx++) { capa_get_entry(&entry, studentNumber, setIdx); totalProbs = entry.e_probs; if( capa_get_header( &header, setIdx ) == -1 ) { Tcl_ResetResult(interp); Tcl_AppendElement(interp,"File Error"); return TCL_OK; } wgt=header.weight; partialCredit=header.partial_credit; for(setScores=0, setValids=0,neverLogin=1,ii=0;ii= '0' && entry.answers[ii] <= '9' ) { setScores += (entry.answers[ii] - '0'); setValids += (wgt[ii] - '0'); neverLogin = 0; } break; } } entry.answers[totalProbs]='\0'; /* get rid of last unknown chars */ entry.tries[3*totalProbs]='\0'; termScores += setScores; termValids += setValids; if(neverLogin) { sprintf(lineOne,"%3d -/%3d %s\n",setIdx,setValids,entry.answers); } else { sprintf(lineOne,"%3d %3d/%3d %s\n",setIdx,setScores,setValids,entry.answers); } Tcl_AppendResult(interp,lineOne,NULL); sprintf(lineOne," %s\n",entry.tries); Tcl_AppendResult(interp,lineOne,NULL); capa_mfree(entry.answers); capa_mfree(entry.tries); } sprintf(lineOne,"========================\n Total = %3d/%3d",termScores,termValids); Tcl_AppendResult(interp,lineOne,NULL); capa_mfree(header.weight); capa_mfree(header.partial_credit); return TCL_OK; } int compare_string( a, b) char *a, *b; { return( strcasecmp(a, b) ); } /* Builds a set summary * Argument: the filename to write to */ int capaGetSetSummary(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { T_student *stuPtr, *currentStudentPtr; T_header a_header; int section, set; int studentCount,currentStudent, setScores, validScores; char fmt1[64], fmt2[64],buf[BUFFER_SIZE],*str1="Student Name",*str2=" "; char *answersPtr; FILE *outputFile; section=atoi(Tcl_GetVar(interp,"gSectionLoad",TCL_GLOBAL_ONLY)); set=atoi(Tcl_GetVar(interp,"gSetLoad",TCL_GLOBAL_ONLY)); Tcl_ResetResult(interp); studentCount = capa_sorted_section(&stuPtr, section); if( studentCount > 0 ) { if( capa_get_header( &a_header, set) == -1 ) { Tcl_Eval(interp,"displayerror \"Cannot open set.db file\""); Tcl_ResetResult(interp); free_students(stuPtr); return TCL_OK; } capa_mfree(a_header.weight); capa_mfree(a_header.partial_credit); sprintf(fmt1,"%%-%ds\t%%%ss\t Score\n", MAX_NAME_CHAR,a_header.num_questions); outputFile=fopen(argv[1],"w"); fprintf(outputFile, "Section %-3d, Set %-3d Score Report\n",section, set); fprintf(outputFile, fmt1,str1,str2); sprintf(fmt1,"%%-%ds\t%%s\t -/%%3d\n", MAX_NAME_CHAR); sprintf(fmt2,"%%-%ds\t%%s\t%%3d/%%3d\n", MAX_NAME_CHAR); for(currentStudentPtr=stuPtr,currentStudent=0;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); if( (setScores = capa_get_score(currentStudentPtr->s_sn, set,&validScores,&answersPtr) ) == -2 ) { Tcl_Eval(interp,"displayerror \"Cannot open set.db file\""); Tcl_ResetResult(interp); free_students(stuPtr); capa_mfree(answersPtr); fclose(outputFile); return TCL_OK; } if( setScores < 0 ) { fprintf(outputFile,fmt1,currentStudentPtr->s_nm,answersPtr,validScores ); } else { fprintf(outputFile,fmt2,currentStudentPtr->s_nm,answersPtr,setScores,validScores ); } capa_mfree(answersPtr); } free_students(stuPtr); fclose(outputFile); } return TCL_OK; } /* builds a term summary * Arguments: filename */ int capaGetTermSummary(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { T_student *studentPtr, *currentStudentPtr; int section, totalSet; int setIndex, setScores, termScores, validScores, termValids; int studentCount,currentStudent=1; char fmt[64]; char *answersPtr,buf[BUFFER_SIZE]; FILE *outputFile; outputFile=fopen(argv[1],"w"); section=atoi(Tcl_GetVar(interp,"gSectionLoad",TCL_GLOBAL_ONLY)); totalSet = howManySetDBFile(); Tcl_ResetResult(interp); studentCount = capa_sorted_section(&studentPtr, section); if( studentCount > 0 ) { for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); sprintf(fmt,"%%-%ds\n", MAX_NAME_CHAR); fprintf(outputFile,fmt,currentStudentPtr->s_nm); for( termScores = 0, termValids = 0, setIndex = 1; setIndex <= totalSet; setIndex++) { if( (setScores = capa_get_score(currentStudentPtr->s_sn, setIndex,&validScores,&answersPtr) ) == -2 ) { sprintf(buf,"displayerror \"Cannot open set%d.db file\"",setIndex); Tcl_Eval(interp,buf); Tcl_ResetResult(interp); capa_mfree(answersPtr); free_students(studentPtr); fclose(outputFile); return TCL_OK; } if( setScores < 0 ) { fprintf(outputFile,"Set %-3d\t%s\t -/%3d\n", setIndex,answersPtr, validScores); } else { fprintf(outputFile, "Set %-3d\t%s\t%3d/%3d\n", setIndex,answersPtr,setScores,validScores ); termScores += setScores; } capa_mfree(answersPtr); termValids += validScores; } fprintf(outputFile,"\t\t\tTerm Score = %3d/%3d\n", termScores,termValids); fprintf(outputFile, "-----------------------------------------------------------------------\n"); } free_students(studentPtr); } fclose(outputFile); return TCL_OK; } extern int Parsemode_f; /* runs capaParse and puts the results into a text widget * Arguments: the name it is registered under (enscriptParse, texParse, * webParse, bubblerParse); what results of the parse to show * 0 (Problem Only), 1 (Question and Answer), 2 (Answer Only); * the set number; either (Random or Specific) student; section; * student Number; student Name ; the name of the variable to * find the widget name of the text widget to put the text into */ int capaTclParse (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { extern char *EndText_p; T_student student; Problem_t *headProblem,*currentProblem; int numOfQuestions,numAnswers,problemNumber=0; int result,i=1,j,length; char *buf, *buf2, *temp, *previewText=NULL; char lower[32],upper[32],ans[32], unit[32]; double targetAns; int c_set; #ifdef GRADER_UPDATE char *update=";update"; #else char *update=" "; #endif switch(argv[0][0]) { case 'e':Parsemode_f = ASCII_MODE;break; case 't':Parsemode_f = TeX_MODE;break; case 'w':Parsemode_f = HTML_MODE;break; case 'b':Parsemode_f = BUBBLE_MODE;break; default: Tcl_ResetResult(interp); Tcl_AppendElement(interp,"Invalid call to capaTclParse\n"); return TCL_ERROR; break; } if ( (previewText = Tcl_GetVar(interp,argv[7], TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)) == NULL) { fprintf(stderr,"Tcl_GetVar error\n"); fprintf(stderr,"%s\n",interp->result); return TCL_ERROR; } c_set = atoi(argv[2]); switch (argv[3][0]) { case 'R': result = capa_pick_student(atoi(argv[4]),&student); if (result == -1) { buf=capa_malloc(BUFFER_SIZE,1); sprintf(buf,"displayError \"There are no students in section %d.\"", atoi(argv[4])); Tcl_Eval(interp,buf); capa_mfree(buf); Tcl_ResetResult(interp); Tcl_AppendElement(interp,"-1"); return TCL_OK; } result = capa_parse(atoi(argv[2]),&headProblem,student.s_sn,&numOfQuestions,NULL); break; case 'S': result = capa_get_student(argv[5],&student); if ((result == -1) || (result == 0)) { buf=capa_malloc(BUFFER_SIZE,1); sprintf(buf,"displayError \"The student %s does not exist.\"", argv[5]); Tcl_Eval(interp,buf); capa_mfree(buf); Tcl_ResetResult(interp); Tcl_AppendElement(interp,"-1"); return TCL_OK; } result = capa_parse(atoi(argv[2]),&headProblem,argv[5],&numOfQuestions,NULL); break; default: Tcl_ResetResult(interp); Tcl_AppendElement(interp,"Invalid 2nd argument to capaTclParse\n"); return TCL_ERROR; break; } if (result==-1) { Tcl_ResetResult(interp); Tcl_AppendElement(interp,"-1"); return TCL_OK; } currentProblem=headProblem; if(argv[1][0] == Q_ANSWER) { /* switch(Parsemode_f) { case ASCII_MODE: sprintf(buf,"Section %d Set %d\n Name: %s PIN: %d\n\n", student.s_sec, atoi(argv[2]), student.s_nm, capa_PIN(student.s_sn, atoi(argv[2]),0)); break; case TeX_MODE: sprintf(buf,"{\\bf Section %d\\qquad Set %d}\\\\\\medskip \n{\\bf Name: \ %s\\qquad PIN: %d}\\\\ \\bigskip\n\n", student.s_sec, atoi(argv[2]), student.s_nm, capa_PIN(student.s_sn, atoi(argv[2]),0)); break; case HTML_MODE: sprintf(buf,"Section %d Set %d\n Name: %s PIN: %d\n\n", student.s_sec, atoi(argv[2]), student.s_nm, capa_PIN(student.s_sn, atoi(argv[2]),0)); break; case BUBBLE_MODE: break; } j=capaPrepareBuffer(buf,buf2,0); sprintf(buf,"%s insert end \" %s \" header",previewText,buf2); if (Tcl_Eval(interp,buf) != TCL_OK) { fprintf(stderr,"Tcl_Eval error\n"); fprintf(stderr,"%s\n",interp->result); return TCL_ERROR; } */ } while (currentProblem!=NULL) { switch (argv[1][0]) { case Q_PROBLEM: if (currentProblem->question) { length=strlen(currentProblem->question); } else { length=0; } buf=capa_malloc(BUFFER_SIZE+(2*length),1); buf2=capa_malloc(BUFFER_SIZE+(2*length),1); if(currentProblem->question) { j=capaPrepareBuffer(currentProblem->question,buf2,0); buf2[j-1]='\n'; buf2[j]='\0'; } else { buf2[0]='\n';buf2[1]='\0'; } if(currentProblem->question) { j=capaPrepareBuffer(currentProblem->question,buf2,0); buf2[j-1]='\n'; buf2[j]='\0'; } else { buf2[0]='\n';buf2[1]='\0'; } switch(Parsemode_f) { case ASCII_MODE: sprintf(buf,"%s insert end \"%s \n-----------\n\n\" problem", previewText,buf2); break; case TeX_MODE: sprintf(buf,"%s insert end \"%s\" problem",previewText,buf2); break; case HTML_MODE: sprintf(buf,"%s insert end \"%s\" problem",previewText,buf2); break; case BUBBLE_MODE: break; } if (Tcl_Eval(interp,buf) != TCL_OK) { fprintf(stderr,"Tcl_Eval error\n"); fprintf(stderr,"%s\n",interp->result); return TCL_ERROR; } capa_mfree(buf); capa_mfree(buf2); break; case Q_PROBLEM_AND_ANSWER: if (currentProblem->question) { length=strlen(currentProblem->question); } else { length=0; } buf=capa_malloc(BUFFER_SIZE+(2*length),1); buf2=capa_malloc(BUFFER_SIZE+(2*length),1); temp=capa_malloc(BUFFER_SIZE+(2*length),1); j=capaPrepareBuffer(currentProblem->question,buf2,0); switch(Parsemode_f) { case ASCII_MODE: sprintf(buf,"%s insert end \"%s \n-----------\n\n\" problem", previewText,buf2); break; case TeX_MODE: sprintf(buf,"%s insert end \"%s\" problem",previewText,buf2); break; case HTML_MODE: sprintf(buf,"%s insert end \"%s\" problem",previewText,buf2); break; case BUBBLE_MODE: break; } if (Tcl_Eval(interp,buf) != TCL_OK) { fprintf(stderr,"Tcl_Eval error\n"); fprintf(stderr,"%s\n",interp->result); return TCL_ERROR; } capa_mfree(buf); capa_mfree(buf2); capa_mfree(temp); capaInsertAnswer(currentProblem,interp,previewText); break; case Q_ANSWER: print_begin_item(Parsemode_f,interp,previewText,problemNumber+1); capaInsertAnswer(currentProblem,interp,previewText); break; } currentProblem=currentProblem->next; problemNumber++; } if( ( EndText_p != NULL) ) { buf=capa_malloc(BUFFER_SIZE+(2*strlen(EndText_p)),1); buf2=capa_malloc(BUFFER_SIZE+(2*strlen(EndText_p)),1); temp=capa_malloc(BUFFER_SIZE+(2*strlen(EndText_p)),1); sprintf(temp,"%s", EndText_p); j=capaPrepareBuffer(temp,buf2,0); sprintf(buf,"%s insert end \"%s\" answer%s",previewText,buf2,update); if (Tcl_Eval(interp,buf) != TCL_OK) { fprintf(stderr,"Tcl_Eval error 7\n"); fprintf(stderr,"%s\n",interp->result); return TCL_ERROR; } capa_mfree(buf); capa_mfree(buf2); capa_mfree(temp); } free_problems(headProblem); if (result==0) { Tcl_ResetResult(interp); Tcl_AppendElement(interp,"0"); } else { buf=capa_malloc(BUFFER_SIZE,1); sprintf(buf,"%d",result); Tcl_ResetResult(interp); Tcl_AppendElement(interp,buf); capa_mfree(buf); } return TCL_OK; } /* setup gQuestionType for all of the questions * Arguments: number of Questions */ int capaGetQuestionTypes(ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { int numQuestions,result,i; T_header header; char buf[BUFFER_SIZE], buf2[BUFFER_SIZE],*weight; if (argc != 2) { Tcl_ResetResult(interp); Tcl_AppendResult(interp,"Wrong number of arguments to getQuestionTypes", NULL); return TCL_ERROR; } numQuestions=atoi(argv[1]); result = capa_get_header(&header,atoi(Tcl_GetVar(interp,"gSetLoad", TCL_GLOBAL_ONLY))); weight=header.weight; if (result == -1) { Tcl_ResetResult(interp); Tcl_AppendResult(interp,"capa_get_header returned error.",NULL); return TCL_ERROR; } for(i=1;i<=numQuestions;i++) { sprintf(buf,"%d",i); switch(header.partial_credit[i-1]) { case '0': Tcl_SetVar2(interp,"gQuestionType",buf,"autoGrade",TCL_GLOBAL_ONLY); break; case '1': Tcl_SetVar2(interp,"gQuestionType",buf,"handGrade",TCL_GLOBAL_ONLY); sprintf(buf,"max%d",i); sprintf(buf2,"%c",weight[i-1]); Tcl_SetVar2(interp,"gAnswer",buf,buf2,TCL_GLOBAL_ONLY); break; default: Tcl_ResetResult(interp); Tcl_AppendResult(interp,"Header for the set.db file is incorrect.", NULL); return TCL_ERROR; break; } } capa_mfree(header.weight); capa_mfree(header.partial_credit); Tcl_ResetResult(interp); return TCL_OK; } /* setup gAnswer for all of the questions * Arguments: number of Questions */ T_entry graderEntry; int capaSetupGAnswer (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { int numQuestions,i,result; char buf[BUFFER_SIZE],buf2[BUFFER_SIZE],*questionType; if (argc != 2) { Tcl_ResetResult(interp); Tcl_AppendResult(interp,"Incorrect number of arguments to setup gAnswer", NULL); return TCL_ERROR; } numQuestions=atoi(argv[1]); result = capa_get_entry(&graderEntry,Tcl_GetVar2(interp,"gGrading","number", TCL_GLOBAL_ONLY), atoi(Tcl_GetVar(interp,"gSetLoad",TCL_GLOBAL_ONLY))); if (result == 0) { Tcl_ResetResult(interp); Tcl_AppendResult(interp,"capa_get_entry returned error.",NULL); return TCL_ERROR; } for(i=1;i<=numQuestions;i++) { sprintf(buf,"%d.tries",i); buf2[0]=graderEntry.tries[(i-1)*3];buf2[1]=graderEntry.tries[(i-1)*3+1]; buf2[2]='\0'; Tcl_SetVar2(interp,"gAnswer",buf,buf2,TCL_GLOBAL_ONLY); sprintf(buf,"%d",i); switch(graderEntry.answers[i-1]) { case '-': Tcl_SetVar2(interp,"gAnswer",buf,"-",TCL_GLOBAL_ONLY); break; case 'y': case 'n': case 'E': sprintf(buf2,"%c",graderEntry.answers[i-1]); Tcl_SetVar2(interp,"gAnswer",buf,buf2,TCL_GLOBAL_ONLY); break; case 'Y': sprintf(buf2,"%c",graderEntry.answers[i-1]); Tcl_SetVar2(interp,"gAnswer",buf,buf2,TCL_GLOBAL_ONLY); questionType=Tcl_GetVar2(interp,"gQuestionType",buf, TCL_GLOBAL_ONLY); switch(questionType[0]) { case 'a': sprintf(buf,"$gGradeCanvas.dash%d configure -state disabled",i); if (Tcl_Eval(interp,buf)!=TCL_OK) return TCL_ERROR; sprintf(buf,"$gGradeCanvas.y%d configure -state disabled",i); if (Tcl_Eval(interp,buf)!=TCL_OK) return TCL_ERROR; sprintf(buf,"$gGradeCanvas.n%d configure -state disabled",i); if (Tcl_Eval(interp,buf)!=TCL_OK) return TCL_ERROR; sprintf(buf,"$gGradeCanvas.e%d configure -state disabled",i); if (Tcl_Eval(interp,buf)!=TCL_OK) return TCL_ERROR; break; case 'h': sprintf(buf,"$gGradeCanvas.hand%d configure -state disabled",i); if (Tcl_Eval(interp,buf)!=TCL_OK) return TCL_ERROR; break; default: Tcl_ResetResult(interp); Tcl_AppendElement(interp,"questionType contains invlaid data in capaSetupGAnswer."); return TCL_ERROR; break; } break; default: sprintf(buf2,"%c",graderEntry.answers[i-1]); Tcl_SetVar2(interp,"gAnswer",buf,buf2,TCL_GLOBAL_ONLY); break; } } Tcl_ResetResult(interp); return TCL_OK; } /* save gAnswer to the set.db file * Arguments: number of Questions */ int capaSaveGAnswer (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { T_entry entry; int numQuestions,i,result; char buf[BUFFER_SIZE],*gAnswer; if (argc != 2) { Tcl_ResetResult(interp); Tcl_AppendResult(interp,"Incorrect number of arguments to save gAnswer",NULL); return TCL_ERROR; } numQuestions=atoi(argv[1]); entry.answers=capa_malloc(numQuestions+1,1); entry.tries=capa_malloc(3*numQuestions+1,1); for(i=0;i= NUM_SET_LIMIT ) ) ) || ( set > maxSet ) ) { sprintf(buf,"displayError \"The set number (%d) doesn't exist.\"",set); Tcl_Eval(interp,buf); Tcl_ResetResult(interp); Tcl_AppendResult(interp,"Error",NULL); return TCL_ERROR; } outputFile=fopen(argv[1],"w"); if ( strcmp(who,"all") == 0 ) whatSection = GET_ALL_SECTIONS; else whatSection = section; studentCount = capa_get_section(&studentPtr, whatSection); if (Tcl_Eval(interp,"updateStatusMessage \"Creating primary sort key\"") != TCL_OK) { free_students(studentPtr); fclose(outputFile); return TCL_ERROR; } if( studentCount > 0 ) { switch (sortOne[1]) { case 'a': /*BY_NAME*/ for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); sprintf(currentStudentPtr->s_key,"%s",currentStudentPtr->s_nm); } break; case 'u': /*BY_NUMBER*/ for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); sprintf(currentStudentPtr->s_key,"%s",currentStudentPtr->s_sn); } break; case 'e': /*BY_SECTION*/ for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); sprintf(currentStudentPtr->s_key,"%03d",currentStudentPtr->s_sec); } break; case 'r': /*BY_GRADE*/ if(strcmp(which,"specific") == 0 ) { for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); if( (setScores = capa_get_score(currentStudentPtr->s_sn,set, &validScores,&answersPtr)) == -2 ) break; if( setScores < 0 ) sprintf(currentStudentPtr->s_key,"-"); else sprintf(currentStudentPtr->s_key,"%03d",setScores); capa_mfree(answersPtr); } } else { for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); for( termScores = 0, termValids = 0, setIndex = 1; setIndex <= set; setIndex++) { if( (setScores = capa_get_score(currentStudentPtr->s_sn,setIndex, &validScores,&answersPtr)) >= 0 ) termScores += setScores; capa_mfree(answersPtr); termValids += validScores; } sprintf(currentStudentPtr->s_key,"%03d",termScores); } } break; } if (Tcl_Eval(interp,"updateStatusMessage \"Creating secondary sort key\"") != TCL_OK) { free_students(studentPtr); fclose(outputFile); return TCL_ERROR; } switch (sortTwo[1]) { case 'a':/*BY_NAME*/ for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); strcat(currentStudentPtr->s_key,currentStudentPtr->s_nm); } break; case 'u':/*BY_NUMBER*/ for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); strcat(currentStudentPtr->s_key,currentStudentPtr->s_sn); } break; case 'e':/*BY_SECTION*/ for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); sprintf(sectionChar,"%03d",currentStudentPtr->s_sec); strcat(currentStudentPtr->s_key,sectionChar); } break; case 'r':/*BY_GRADE*/ if(strcmp(which,"specific") == 0 ) { for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); if( (setScores = capa_get_score(currentStudentPtr->s_sn,set,&validScores, &answersPtr) ) == -2 ) break; if( setScores < 0 ) strcat(currentStudentPtr->s_key,"-"); else { sprintf(grades,"%03d",setScores); strcat(currentStudentPtr->s_key,grades); } capa_mfree(answersPtr); } } else { for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); for( termScores = 0, termValids = 0, setIndex = 1; setIndex <= set; setIndex++) { if( (setScores = capa_get_score(currentStudentPtr->s_sn,setIndex, &validScores,&answersPtr) ) >= 0 ) termScores += setScores; capa_mfree(answersPtr); termValids += validScores; } sprintf(grades,"%03d",termScores); strcat(currentStudentPtr->s_key,grades); } } break; } if (Tcl_Eval(interp,"updateStatusMessage \"Sorting\"") != TCL_OK) { free_students(studentPtr); fclose(outputFile); return TCL_ERROR; } msort_main(&studentPtr); Tcl_ResetResult(interp); sprintf(fmt,"%%-%ds\t%%-%ds %%2d\t", MAX_NAME_CHAR,MAX_STUDENT_NUMBER); if (Tcl_Eval(interp,"updateStatusMessage \"Creating Report\"") != TCL_OK) { free_students(studentPtr); fclose(outputFile); return TCL_ERROR; } for(currentStudentPtr=studentPtr,currentStudent=1;currentStudentPtr; currentStudentPtr=currentStudentPtr->s_next,currentStudent++) { sprintf(buf,"updateStatusBar %f",(float)currentStudent/(float)studentCount); Tcl_Eval(interp,buf); fprintf(outputFile,fmt,currentStudentPtr->s_nm,currentStudentPtr->s_sn, currentStudentPtr->s_sec); if( strcmp(which,"specific") == 0) { setScores = 0; validScores = 0; if( (setScores = capa_get_score(currentStudentPtr->s_sn,set,&validScores,&answersPtr) ) == -2 ) break; if( setScores < 0 ) { fprintf(outputFile, " -\t%3d\n", validScores); } else { fprintf(outputFile, "%3d\t%3d\n",setScores, validScores); } capa_mfree(answersPtr); } else { for( setScores=0, validScores=0, termScores = 0, termValids = 0, setIndex = 1; setIndex <= set; setIndex++) { if( (setScores = capa_get_score(currentStudentPtr->s_sn,setIndex, &validScores,&answersPtr) ) >= 0 ) termScores += setScores; capa_mfree(answersPtr); termValids += validScores; if( setScores >= 0 ) { fprintf(outputFile, "%3d ",setScores); } else { fprintf(outputFile, " - "); } } fprintf(outputFile, "\t %3d\t%3d\n",termScores,termValids); } } free_students(studentPtr); } fclose(outputFile); return TCL_OK; } /* set the gAnswer score to what ever the user entered * Arguments: problemNumber */ int capaSetHandGrade (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { int problemNumber=atoi(argv[1]),handGrade,maxGrade; char *handGradeChar,buf[BUFFER_SIZE]; handGradeChar=Tcl_GetVar(interp,"gNewHandGrade",TCL_GLOBAL_ONLY); sprintf(buf,"max%d",problemNumber); maxGrade=atoi(Tcl_GetVar2(interp,"gAnswer",buf,TCL_GLOBAL_ONLY)); if (isdigit(handGradeChar[0])) { handGrade=atoi(handGradeChar); if (handGrade > maxGrade) { sprintf(buf,"displayError \"Invalid response, you must enter a number between 0 and %d, or an E to excuse the problem.\"",maxGrade); if (Tcl_Eval(interp,buf)!=TCL_OK) { return TCL_ERROR; } } else { sprintf(buf,"%d",handGrade); Tcl_SetVar2(interp,"gAnswer",argv[1],buf,TCL_GLOBAL_ONLY); } } else { if (handGradeChar[0]=='E') { Tcl_SetVar2(interp,"gAnswer",argv[1],"E",TCL_GLOBAL_ONLY); } else { sprintf(buf,"displayError \"Invalid response, you must enter a number between 0 and %d, or an E to excuse the problem.\"",maxGrade); if (Tcl_Eval(interp,buf)!=TCL_OK) return TCL_ERROR; } } Tcl_ResetResult(interp); return TCL_OK; } /* save gAnswer to the set.db file * Arguments: setNum, questNum, stuId, score */ int capaSetScore (ClientData clientdata, Tcl_Interp *interp, int argc, char *argv[]) { T_entry entry; int score,i,result,question,numQuest,set; char buf[BUFFER_SIZE],*gAnswer,*stuId; T_header header; if (argc != 5) { Tcl_ResetResult(interp); Tcl_AppendResult(interp,"Incorrect number of arguments to save gAnswer",NULL); return TCL_ERROR; } set=atoi(argv[1]); question=atoi(argv[2]); stuId=argv[3]; score=atoi(argv[4]); result=capa_get_header(&header,set); numQuest=atoi(header.num_questions); result = capa_get_entry(&entry,stuId,set); entry.answers=capa_malloc(numQuest+1,1); entry.tries=capa_malloc(3*numQuest+1,1); for(i=0;i