/* c interfaces for the scorer program 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. */ /* * scorer.funct.c * Guy Albertelli II 1997 */ #include #include #include #include #ifdef NeXT #endif #ifdef linux #include #include #include #include #include #endif #include #include #include "pProj/capaCommon.h" #include "scorer.h" #include "manager.h" #ifdef DMALLOC #include #endif extern int Parsemode_f; char NUMBER[10]={'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; char LETTER[10]={'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'}; PIDPINlist *studentList; /* 2 arguments, string 1 and string 2 result is an integer of # charactes the same*/ int compareCapaID(ClientData notused, Tcl_Interp *interp, int argc, char* argv[]) { int same=0,length,i; char buf[MAX_BUFFER_SIZE]; length=strlen(argv[1]); for(i=0;ianswer)+MAX_LINE_LENGTH,sizeof(char)); sprintf(buf,"%s ",curProblem->answer); Tcl_AppendStringsToObj(tclResult,buf,NULL); capa_mfree(buf); curProblem=curProblem->next; } free_problems(headProblem); Tcl_SetObjResult(interp,tclResult); Tcl_DecrRefCount(tclResult); return TCL_OK; } /*needs num (the unique ident)*/ int freeStudentList(ClientData notused, Tcl_Interp *interp, int agrc, char* argv[]) { int i,num = atoi(argv[1]); PIDPINlist *cur,*prev; if (!studentList) { return TCL_OK; } cur=studentList; prev=NULL; while((cur->num!=num) && cur->next) { prev=cur; cur=cur->next; } if (cur->num!=num) { return TCL_OK; } capa_mfree(cur->classname); for(i=0;inumStudents;i++) capa_mfree(cur->classList[i].capaid_plus); capa_mfree((char*)cur->classList); if ( prev != NULL ) { prev->next=cur->next; } else { if (cur->next) studentList=cur->next; } capa_mfree((char*)cur); return TCL_OK; } /*needs num (unique ident), classname, setId, capaid_plus size*/ int buildStudentList(ClientData notused, Tcl_Interp *interp, int argc, char* argv[]) { long i,j,numStudents,num,capaidplusSize,setId,part1,part2; T_student *curStudent,*headStudent; PIDPINlist *cur; char *buf,*buf2; Tcl_Obj* tclResult; if (argc!=5) { Tcl_SetResult(interp,"usage is: number classname setId capa_id_plus_size", TCL_VOLATILE); return TCL_ERROR; } if (studentList) { cur=studentList; while(cur->next) { cur=cur->next; } cur->next=(PIDPINlist*)capa_malloc(1,sizeof(PIDPINlist)); cur=cur->next; } else { studentList=(PIDPINlist*)capa_malloc(1,sizeof(PIDPINlist)); cur=studentList; } cur->classname=(char*)capa_malloc(strlen(argv[2]),sizeof(char)); strcpy(argv[2],cur->classname); cur->num=num=atoi(argv[1]); setId=atoi(argv[3]); capaidplusSize=atoi(argv[4]); numStudents=capa_get_section(&headStudent, 0); if ( numStudents == 0 ) { Tcl_SetResult(interp,"No students in class.",TCL_VOLATILE); return TCL_ERROR; } else if ( numStudents < 0 ) { Tcl_SetResult(interp,"Unable to read the classl file",TCL_VOLATILE); return TCL_ERROR; } cur->classList=(PIDPIN*)capa_malloc(numStudents,sizeof(PIDPIN)); curStudent=headStudent; tclResult=Tcl_NewStringObj("",0); Tcl_IncrRefCount(tclResult); for(i=0;curStudent;curStudent=curStudent->s_next,i++) { capa_seed(&part1, &part2, curStudent->s_sn);setall(part1, part2); strcpy(cur->classList[i].PID,curStudent->s_sn); cur->classList[i].PIN=capa_PIN(curStudent->s_sn,setId,0); cur->classList[i].capaid_plus=capa_id_plus(curStudent->s_sn,setId,capaidplusSize); j=strlen(cur->classList[i].capaid_plus)+MAX_PIN_CHAR+ strlen(cur->classList[i].PID)+strlen(curStudent->s_nm)+MAX_LINE_LENGTH; buf=(char*)capa_malloc(j,sizeof(char)); sprintf(buf,"{{%s} %s %d %s} ",curStudent->s_nm,curStudent->s_sn, cur->classList[i].PIN,cur->classList[i].capaid_plus); Tcl_AppendStringsToObj(tclResult,buf,NULL); capa_mfree(buf); } Tcl_SetObjResult(interp,tclResult); Tcl_IncrRefCount(tclResult); free_students(headStudent); cur->numStudents=numStudents; return TCL_OK; } int gradeQuestion(Question questions[MAX_QUEST],int questionIndex, Problem_t *problem,Student *student,Flags* flags) { int numRight=0,leafs; char one=1,zero=0; char *ansOn[20],*stuOn[20]; int i,j; int sortArray[256]; char newAnswer[MAX_LINE_LENGTH],*oldAnswer; switch(questions[questionIndex].type) { case ONE_OUT_OF_8: case GLE: case TF: case SINGLE_DIGIT: if (!flags->log) printf("The correct answer:%10s The student's answer:%10s, \t", problem->answer,student->Answers[questionIndex]); for(leafs=0;problem->answer[leafs]!='\0';leafs++) if (problem->answer[leafs]==student->Answers[questionIndex][leafs]) numRight++; if (!flags->log) printf("%d right\n",numRight); break; case ASSIGNED: if (!flags->log) printf("The student got a %s out of %d\n", student->Answers[questionIndex], questions[questionIndex].points); if (isspace(student->Answers[questionIndex][0])) numRight=0; else numRight=(int)(student->Answers[questionIndex][0]-'0'); break; case N_OUT_OF_M: if (!flags->log) printf("The correct answer:%10s The student's answer:%10s, \t", problem->answer,student->Answers[questionIndex]); if (problem->ans_type == ANSWER_IS_CHOICE) { for(i=0;i<255;i++) sortArray[i]=0; for(i=0;i< strlen(problem->answer);i++) sortArray[(int)problem->answer[i]]=1; for(i=0,j=0;i<255;i++) { if (sortArray[i]) { newAnswer[j]=i; j++; } } newAnswer[j]='\0'; if (!flags->log) printf("\nThe sorted correct answer:%10s\t\t\t",newAnswer); oldAnswer=problem->answer; problem->answer=newAnswer; } for(leafs=0;questions[questionIndex].leafs>leafs;leafs++) { ansOn[leafs]=strchr(problem->answer,('A'+(char)leafs)); } for(leafs=0;questions[questionIndex].leafs>leafs;leafs++) { if (ansOn[leafs] != NULL ) ansOn[leafs]=&one; else ansOn[leafs]=&zero; } for(leafs=0;questions[questionIndex].leafs>leafs;leafs++) { stuOn[leafs]=strchr(student->Answers[questionIndex], ('A'+(char)leafs)); } for(leafs=0;questions[questionIndex].leafs>leafs;leafs++) { if (stuOn[leafs] != NULL) stuOn[leafs]=&one; else stuOn[leafs]=&zero; } for(leafs=0;questions[questionIndex].leafs>leafs;leafs++) if (ansOn[leafs] == stuOn[leafs]) numRight++; if (!flags->log) printf("%d right\n",numRight); if (problem->ans_type == ANSWER_IS_CHOICE) problem->answer=oldAnswer; break; case STRING_MATCH: if (!flags->log) printf("The correct answer:%10s The student's answer:%10s, ", problem->answer,student->Answers[questionIndex]); if (problem->ans_type == ANSWER_IS_CHOICE) { for(i=0;i<255;i++) sortArray[i]=0; for(i=0;i< strlen(problem->answer);i++) sortArray[(int)problem->answer[i]]=1; for(i=0,j=0;i<255;i++) { if (sortArray[i]) { newAnswer[j]=i; j++; } } newAnswer[j]='\0'; if (!flags->log) printf("\nThe sorted correct answer:%10s\t\t\t",newAnswer); oldAnswer=problem->answer; problem->answer=newAnswer; } if (!(strcasecmp(problem->answer,student->Answers[questionIndex]))) { if (!flags->log) printf("Answer is correct\n"); numRight=questions[questionIndex].points; } else { if (!flags->log) printf("Answer is wrong\n"); numRight=0; } if (problem->ans_type == ANSWER_IS_CHOICE) problem->answer=oldAnswer; break; default: fprintf(stderr,"Unknown question type while grading, %c.\nDying.\n", questions[questionIndex].type); exit(E_UNKNOWN_QTYPE); break; } return numRight; }