File:
[LON-CAPA] /
capa /
capa51 /
Historic /
Scorer /
scorer.c
Revision
1.1:
download - view:
text,
annotated -
select for diffs
Wed Aug 30 15:02:30 2000 UTC (24 years, 5 months ago) by
albertel
Branches:
MAIN
CVS tags:
version_2_9_X,
version_2_9_99_0,
version_2_9_1,
version_2_9_0,
version_2_8_X,
version_2_8_99_1,
version_2_8_99_0,
version_2_8_2,
version_2_8_1,
version_2_8_0,
version_2_7_X,
version_2_7_99_1,
version_2_7_99_0,
version_2_7_1,
version_2_7_0,
version_2_6_X,
version_2_6_99_1,
version_2_6_99_0,
version_2_6_3,
version_2_6_2,
version_2_6_1,
version_2_6_0,
version_2_5_X,
version_2_5_99_1,
version_2_5_99_0,
version_2_5_2,
version_2_5_1,
version_2_5_0,
version_2_4_X,
version_2_4_99_0,
version_2_4_2,
version_2_4_1,
version_2_4_0,
version_2_3_X,
version_2_3_99_0,
version_2_3_2,
version_2_3_1,
version_2_3_0,
version_2_2_X,
version_2_2_99_1,
version_2_2_99_0,
version_2_2_2,
version_2_2_1,
version_2_2_0,
version_2_1_X,
version_2_1_99_3,
version_2_1_99_2,
version_2_1_99_1,
version_2_1_99_0,
version_2_1_3,
version_2_1_2,
version_2_1_1,
version_2_1_0,
version_2_12_X,
version_2_11_X,
version_2_11_6_msu,
version_2_11_6,
version_2_11_5_msu,
version_2_11_5,
version_2_11_4_uiuc,
version_2_11_4_msu,
version_2_11_4,
version_2_11_3_uiuc,
version_2_11_3_msu,
version_2_11_3,
version_2_11_2_uiuc,
version_2_11_2_msu,
version_2_11_2_educog,
version_2_11_2,
version_2_11_1,
version_2_11_0_RC3,
version_2_11_0_RC2,
version_2_11_0_RC1,
version_2_11_0,
version_2_10_X,
version_2_10_1,
version_2_10_0_RC2,
version_2_10_0_RC1,
version_2_10_0,
version_2_0_X,
version_2_0_99_1,
version_2_0_2,
version_2_0_1,
version_2_0_0,
version_1_99_3,
version_1_99_2,
version_1_99_1_tmcc,
version_1_99_1,
version_1_99_0_tmcc,
version_1_99_0,
version_1_3_X,
version_1_3_3,
version_1_3_2,
version_1_3_1,
version_1_3_0,
version_1_2_X,
version_1_2_99_1,
version_1_2_99_0,
version_1_2_1,
version_1_2_0,
version_1_1_X,
version_1_1_99_5,
version_1_1_99_4,
version_1_1_99_3,
version_1_1_99_2,
version_1_1_99_1,
version_1_1_99_0,
version_1_1_3,
version_1_1_2,
version_1_1_1,
version_1_1_0,
version_1_0_99_3,
version_1_0_99_2,
version_1_0_99_1,
version_1_0_99,
version_1_0_3,
version_1_0_2,
version_1_0_1,
version_1_0_0,
version_0_99_5,
version_0_99_4,
version_0_99_3,
version_0_99_2,
version_0_99_1,
version_0_99_0,
version_0_6_2,
version_0_6,
version_0_5_1,
version_0_5,
version_0_4,
stable_2002_spring,
stable_2002_july,
stable_2002_april,
stable_2001_fall,
loncapaMITrelate_1,
language_hyphenation_merge,
language_hyphenation,
conference_2003,
bz6209-base,
bz6209,
STABLE,
HEAD,
GCI_3,
GCI_2,
GCI_1,
CAPA_5-1-6,
CAPA_5-1-5,
CAPA_5-1-4_RC1,
BZ4492-merge,
BZ4492-feature_horizontal_radioresponse,
BZ4492-feature_Support_horizontal_radioresponse,
BZ4492-Support_horizontal_radioresponse
- documentation updates
/*
* scorer.c
* Copyright Guy Albertelli II 1997
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#ifdef NeXT
#endif
#ifdef linux
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#endif
#include "Capa/capaCommon.h"
#include "scorer.h"
extern int Parsemode_f;
void initScreen()
{
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
printf("Welcome to Scorer, the Automated Scoring Office converter.\n");
printf("By: Guy Albertelli II\n");
printf("Version %s.%s for %s\n\n\n",MAJORVER,MINORVER,ARCHSTR);
}
void getClassInfo(Flags *flags,FILE** scantron)
{
char buffer[MAX_LINE_LENGTH],buffer2[MAX_LINE_LENGTH];
int done=FALSE;
printf("What is the class name?");
scanf("%s",flags->Class);
flags->Class[8]='\0';
printf("What is the SetId?");
scanf("%d",&(flags->SetId));
while(!done)
{
printf("What is the name of the scoring offices report file?");
scanf("%s",buffer);
*scantron=fopen(buffer,"r");
if (*scantron != NULL)
{
rewind(*scantron);
if (EOF == fscanf(*scantron,"%s",buffer2))
printf("This file appears to be empty. Please enter a new name.\n");
else
{
rewind(*scantron);
done=1;
}
}
else
printf("Unable to open the report file %s\n",buffer);
}
}
int openOutputFile(char filename[MAX_LINE_LENGTH], FILE ** outputFile)
{
char buf[MAX_LINE_LENGTH];
*outputFile=fopen(filename,"r+");
if (*outputFile != NULL)
{
rewind(*outputFile);
if (EOF == fscanf(*outputFile,"%s",buf))
buf[0]='\0';
}
if (*outputFile==NULL || buf[0]=='\0')
{
if (*outputFile != NULL)
fclose(*outputFile);
*outputFile=fopen(filename,"w+");
if (*outputFile==NULL)
{
fprintf(stderr,"Unable to open the output file %s\n",filename);
return SCO_FATALERROR;
}
else
return SCO_NEW;
}
else
{
rewind(*outputFile);
return SCO_EXIST;
}
}
void initValues(Question questions[MAX_QUEST],Flags *flags)
{
int i;
flags->NumQuestions=0;
flags->CheckPIN=TRUE;
flags->AnonMode=FALSE;
flags->CheckSpaces=FALSE;
flags->SurveyMode=FALSE;
flags->SurveyHeader=FALSE;
flags->Pause=FALSE;
flags->PauseTime=0.0;
flags->IdFormat=ANUMBER_FORMAT;
flags->CheckMultipleMarks=FALSE;
flags->QueryAboutPID=FALSE;
flags->log=TRUE;
for(i=0;i<MAX_QUEST;i++)
{
questions[i].type='\0';
questions[i].points=0;
questions[i].leafs=0;
}
}
int getPreviousValues(FILE *outputFile, Question questions[MAX_QUEST],
Flags *flags)
{
char prevClass[MAX_LINE_LENGTH],prevFlags[MAX_LINE_LENGTH],
prevQuestions[MAX_LINE_LENGTH],buf[MAX_LINE_LENGTH];
int prevSetId,prevNumQuestions,done,i;
float pauseTime;
rewind(outputFile);
fscanf(outputFile,"%s %d %d %s %f %s",prevClass,&prevSetId,&prevNumQuestions,
prevFlags,&pauseTime,prevQuestions);
if ( strcmp(prevClass,flags->Class)!=0)
{
printf("Classname as found in the current scorer.output file: %s\n",
prevClass);
printf("Classname as entered: %s\n",flags->Class);
printf("Please select one as correct. previous or new (p/n).\n");
done=FALSE;
while(!done)
{
scanf("%s",buf);
switch(buf[0])
{
case 'n':case'N':
done=TRUE;
break;
case 'p':case'P':
done=TRUE;
strcpy(flags->Class,prevClass);
break;
default:
printf("Please enter one of previous(p) or new(n).\n");
break;
}
}
}
if ( prevSetId != flags->SetId )
{
printf("SetId as found in the current scorer.output file: %d\n",
prevSetId);
printf("SetId as entered: %d\n",flags->SetId);
printf("Please select one as correct. previous or new (p/n).\n");
done=FALSE;
while(!done)
{
scanf("%s",buf);
switch(buf[0])
{
case 'n':case'N':
done=TRUE;
break;
case 'p':case'P':
done=TRUE;
flags->SetId=prevSetId;
break;
default:
printf("Please enter one of previous(p) or new(n).\n");
break;
}
}
}
flags->NumQuestions=prevNumQuestions;
flags->CheckPIN=(int)(prevFlags[0]-'0');
flags->AnonMode=(int)(prevFlags[1]-'0');
flags->CheckSpaces=(int)(prevFlags[2]-'0');
flags->SurveyMode=(int)(prevFlags[3]-'0');
flags->SurveyHeader=(int)(prevFlags[4]-'0');
flags->Pause=(int)(prevFlags[5]-'0');
flags->PauseTime=pauseTime;
flags->IdFormat=(int)(prevFlags[6]-'0');
flags->CheckMultipleMarks=(int)(prevFlags[7]-'0');
flags->QueryAboutPID=(int)(prevFlags[8]-'0');
flags->log=(int)(prevFlags[9]-'0');
for(i=0;i<flags->NumQuestions;i++)
{
questions[i].type=prevQuestions[3*i];
questions[i].points=(int)(prevQuestions[3*i+1]-'0');
questions[i].leafs=(int)(prevQuestions[3*i+2]-'0');
}
for(i=flags->NumQuestions;i<MAX_QUEST;i++)
{
questions[i].type='\0';
questions[i].points=0;
questions[i].leafs=0;
}
return 0;
}
int printFlagMenu(Flags *flags, int *flagToModify)
{
int i=0;
if(flags->SurveyMode)
{
printf("%d. The Paper being graded is a Survey.\n",++i);
flagToModify[i]=SURVEY_MODE;
if(flags->SurveyHeader)
printf("%d. The Survey has a header.\n",++i);
else
printf("%d. The Survey does not have a header.\n",++i);
flagToModify[i]=SURVEY_HEADER;
}
else
{
printf("%d. The paper being graded is an Exam or Quiz.\n",++i);
flagToModify[i]=SURVEY_MODE;
if(flags->CheckPIN)
{
printf("%d. The coded CAPA ID will be checked for validity.\n",++i);
flagToModify[i]=CHECK_PIN;
if(flags->AnonMode)
{
printf("%d. Scorer will run in Anonymous Mode. (search for \n\tthe correct Student Number based on the CAPA ID)\n",++i);
flagToModify[i]=ANON_MODE;
if(flags->QueryAboutPID)
printf("%d. Scorer will ask which PID to use if multiple are found.\n",++i);
else
printf("%d. Scorer will pick highest score if multiple PIDs found.\n",++i);
flagToModify[i]=QUERY_ABOUT_PID;
}
else
{
printf("%d. Scorer will not run in Anonymous Mode. (Bubbled \n\tstudent number is correct for the CAPA ID.)\n",++i);
flagToModify[i]=ANON_MODE;
}
}
else
{
printf("%d. The coded CAPA ID will be ignored.\n",++i);
flagToModify[i]=CHECK_PIN;
}
if(flags->CheckSpaces)
{
if (flags->log)
printf("%d. Scorer will log sheets containing blank answers.\n",++i);
else
printf("%d. Scorer will issue a warning and pause when encountering blank answers.\n",++i);
}
else
{
printf("%d. Scorer will ignore blank answers.\n",++i);
}
flagToModify[i]=CHECK_SPACES;
if(flags->CheckMultipleMarks)
{
if (flags->log)
printf("%d. Scorer will log answer sheets containing multiple marks.\n",++i);
else
printf("%d. Scorer will issue a warning and pause when encountering multiple marks.\n",++i);
}
else
{
printf("%d. Scorer will mark multiple marks wrong.\n",++i);
}
flagToModify[i]=MULTIPLE_MARKS;
switch(flags->IdFormat)
{
case ANUMBER_FORMAT:
printf("%d. The StudentId is in A<number> format.\n",++i);
break;
case SOC_SEC_FORMAT:
printf("%d. The StudentId is in Social Security format.\n",++i);
break;
default:
flags->IdFormat=ANUMBER_FORMAT;
printf("%d. The StudentId is in A<number> format.\n",++i);
break;
}
flagToModify[i]=ID_FORMAT;
}
if (flags->Pause)
printf("%d. The program will pause %.2f seconds between papers.\n",++i,
flags->PauseTime);
else
printf("%d. The program will process papers as quickly as possible.\n",
++i);
flagToModify[i]=PAUSE_TIME;
if (flags->log)
printf("%d. The program will log all errors.\n",++i);
else
printf("%d. The program will query user on all errors.\n",++i);
flagToModify[i]=LOGGING;
return i;
}
int getYesOrNo()
{
int done=FALSE;
char buf[MAX_LINE_LENGTH];
while(!done)
{
scanf("%s",buf);
switch(buf[0])
{
case 'n':case'N':
return NO;
done=TRUE;
break;
case 'y':case'Y':
return YES;
done=TRUE;
break;
default:
printf("Please enter y or n.");
done=FALSE;
break;
}
}
exit(E_GETYESNO);
return -1;
}
void modifyFlag(Flags *flags,int *flagToModify,int i)
{
int valid=FALSE;
int done=FALSE;
char buf[MAX_LINE_LENGTH];
switch(flagToModify[i])
{
case CHECK_PIN:
printf("Should the student coded CAPA ID be checked for correctness?\n");
printf("(y or n)");
flags->CheckPIN=getYesOrNo();
break;
case ANON_MODE:
printf("Should scorer run in Anonymous mode (search for correct \n");
printf("Student Number based on the CAPA ID)? (y or n)");
flags->AnonMode=getYesOrNo();
break;
case QUERY_ABOUT_PID:
printf("Should scorer Query you when multiple PIDs match a single PIN.(y or n)\n");
flags->QueryAboutPID=getYesOrNo();
break;
case CHECK_SPACES:
printf("Should scorer check for blank answers and issue a warning \n");
printf("when one is encountered? (y or n)");
flags->CheckSpaces=getYesOrNo();
break;
case MULTIPLE_MARKS:
printf("Should scorer check for multiple marks and issue a warning \n");
printf("when encountered? (y or n)");
flags->CheckMultipleMarks=getYesOrNo();
break;
case SURVEY_MODE:
printf("Is this a survey?(y or n)");
flags->SurveyMode=getYesOrNo();
break;
case SURVEY_HEADER:
printf("Does the form include a Header?(y or n)");
flags->SurveyHeader=getYesOrNo();
break;
case PAUSE_TIME:
printf("Do you wish for there to be a pause between papers?(y or n)");
flags->Pause=getYesOrNo();
if (flags->Pause)
{
printf("Please enter the minimum delay between papers in seconds.\n");
valid=FALSE;
while(!valid)
{
scanf("%s",buf);
flags->PauseTime=(float)atof(buf);
if (flags->PauseTime < 0.00001)
{
printf("You have entered a rather short time, are you sure you meant %f seconds?",flags->PauseTime);
switch(getYesOrNo())
{
case NO:
printf("Please enter the minimum delay between papers.\n");
break;
case YES:
valid=TRUE;
break;
default:
fprintf(stderr,"getYesOrNo returned a bad result\n");
exit(E_GETYESNO);
break;
}
}
else
valid=TRUE;
}
}
else
flags->PauseTime=0.0;
break;
case ID_FORMAT:
printf("Is the StudentID Format A<number> or Social Security? (a or s)");
while(!done)
{
scanf("%s",buf);
switch(buf[0])
{
case 'a':case'A':
flags->IdFormat=ANUMBER_FORMAT;
done=TRUE;
break;
case 's':case'S':
flags->IdFormat=SOC_SEC_FORMAT;
done=TRUE;
break;
default:
printf("Please enter a or s.");
done=FALSE;
break;
}
}
break;
case LOGGING:
printf("Should Scorer log errors?(y or n)");
flags->log=getYesOrNo();
break;
default:
fprintf(stderr,"Corrupted information in modifyFlag, i=%d\n",i);
fprintf(stderr,"flagToModify[i]=%d",flagToModify[i]);
exit(E_MODIFYFLAG);
break;
}
}
void checkFlagConsistency(Flags *flags)
{
if(flags->SurveyMode)
{
flags->CheckPIN=FALSE;
flags->AnonMode=FALSE;
flags->QueryAboutPID=FALSE;
flags->CheckSpaces=FALSE;
flags->CheckMultipleMarks=FALSE;
}
else
{
flags->SurveyHeader=FALSE;
if(flags->CheckPIN);
else
flags->AnonMode=FALSE;
}
if (!flags->AnonMode) flags->QueryAboutPID=FALSE;
}
void getFlags(Flags *flags)
{
int done=FALSE,valid=FALSE,i,flagToModify[MAX_NUM_FLAG];
char buf[MAX_LINE_LENGTH];
while(!done)
{
i=printFlagMenu(flags,flagToModify);
printf("Please select which one of the above (1-%d) you wish to \n",i);
printf("change. Otherwise enter 0 (zero) to continue.\n");
valid=FALSE;
while(!valid)
{
scanf("%s",buf);
if (isdigit(buf[0]))
{
i=atoi(buf);
valid=TRUE;
}
else
printf("Please enter a number between (0-%d)\n",i);
}
if (i)
modifyFlag(flags,flagToModify,i);
else
done=TRUE;
}
checkFlagConsistency(flags);
}
void printQuestions(Question questions[MAX_QUEST],int numQuestions)
{
int i;
for(i=0;i<numQuestions;i++)
{
printf("%d. ",i+1);
switch(questions[i].type)
{
case ONE_OUT_OF_8:
printf("One out of 8. ");
break;
case GLE:
printf("Choose one of >, <, =, ");
break;
case TF:
printf("True or False. ");
break;
case ASSIGNED:
printf("Assigned Score. ");
break;
case N_OUT_OF_M:
printf("Pick N out of M. ");
break;
case SINGLE_DIGIT:
printf("Single digit answer. ");
break;
case STRING_MATCH:
printf("Exact string matching.(10 or less bubbles) ");
break;
default:
fprintf(stderr,"\nCorrupt data in Questions struct while inside printQuestions. Dying\n");
exit(E_PRINTQUESTIONS);
break;
}
printf(" %d leafs, Worth: %d points\n",questions[i].leafs,
questions[i].points);
}
}
int wantToChangeQuestions()
{
int done=FALSE;
char buf[MAX_LINE_LENGTH];
printf("Do you want to change any of the above?(y or n)\n");
while(!done)
{
scanf("%s",buf);
switch(buf[0])
{
case 'n':case'N':
return 0;
done=TRUE;
break;
case 'y':case 'Y':
return 1;
done=TRUE;
break;
default:
printf("Please enter either (y or n).\n");
break;
}
}
return -1;
}
void printQuestionMenu()
{
printf("For Each Question enter \"%c\" for a one out of 8\n",ONE_OUT_OF_8);
printf(" \"%c\" for a GLE type\n",GLE);
printf(" \"%c\" for a TF type.\n",TF);
printf(" \"%c\" for an assigned score.\n",ASSIGNED);
printf(" \"%c\" for an n out of m.\n",N_OUT_OF_M);
printf(" \"%c\" for single digit answer.\n",
SINGLE_DIGIT);
printf(" \"%c\" for exact string matching (8 or less bubbles)\n",
STRING_MATCH);
printf(" \"%c\" to print this menu again\n",
QUESTION_MENU);
printf(" \"%c\" to stop entering questions\n",
QUESTION_STOP);
}
int getSingleDigit()
{
int done=FALSE;
char buf[MAX_LINE_LENGTH];
while(!done)
{
scanf("%s",buf);
if (isdigit(buf[0]) && (atoi(buf) >=1) && (atoi(buf) <=9))
{
done=TRUE;
return atoi(buf);
}
else
printf("Please enter a digit between 1 and 9\n");
}
return 0;
}
int getNewQuestion(Question questions[MAX_QUEST],int numQuestions)
{
int done=FALSE;
char buf[MAX_LINE_LENGTH];
printf("Question#%2d: (enter %c to see menu): ",numQuestions+1,QUESTION_MENU);
while(!done)
{
scanf("%s",buf);
questions[numQuestions].leafs=1;
switch(buf[0])
{
case GLE:
case TF:
printf("How many parts to the problem?");
if (!(questions[numQuestions].leafs=getSingleDigit()))
{
fprintf(stderr,"Weird result from getSingleDigit\n");
exit(E_SINGLEDIGIT);
}
case ONE_OUT_OF_8:
case ASSIGNED:
case SINGLE_DIGIT:
case STRING_MATCH:
printf("How many points are possible?");
done=TRUE;
break;
case N_OUT_OF_M:
printf("What is m in the problem?");
if (!(questions[numQuestions].leafs=getSingleDigit()))
{
fprintf(stderr,"Weird result from getSingleDigit\n");
exit(E_SINGLEDIGIT);
}
printf("How many points are possible?");
done=TRUE;
break;
case QUESTION_MENU:
printQuestionMenu();
printf("Question#%2d: ",numQuestions+1);
break;
case QUESTION_STOP:
return 0;
break;
default:
printf("Please enter one of %c,%c,%c,%c,%c,%c,%c,%c,%c.\n",
ONE_OUT_OF_8,GLE,TF,ASSIGNED,N_OUT_OF_M,SINGLE_DIGIT,
STRING_MATCH,QUESTION_MENU,QUESTION_STOP);
printf("Question#%2d: ",numQuestions+1);
break;
}
}
questions[numQuestions].type=buf[0];
if (!(questions[numQuestions].points=getSingleDigit()))
{
fprintf(stderr,"Weird result from getSingleDigit\n");
exit(E_SINGLEDIGIT);
}
return 1;
}
void printModifyQuestionMenu()
{
printf("(a)dd a question\n");
printf("(c)hange a question\n");
printf("(d)elete a question\n");
printf("(f)inished changing\n");
}
void addQuestion(Question questions[MAX_QUEST],int *numQuestions)
{
printQuestionMenu();
if (getNewQuestion(questions,*numQuestions))
(*numQuestions)=(*numQuestions)+1;
}
void changeQuestion(Question questions[MAX_QUEST],int numQuestions)
{
int done=FALSE;
char buf[MAX_LINE_LENGTH];
printf("Which question do you wish to change?(1-%d) ",numQuestions);
printf("Or 0 for none\n");
while(!done)
{
scanf("%s",buf);
if(isdigit(buf[0]) && (atoi(buf) >= 0) && (atoi(buf) <= numQuestions))
done=TRUE;
else
printf("Please enter a number between 0 and %d.\n",numQuestions);
}
if (atoi(buf) !=0)
{
printQuestionMenu();
getNewQuestion(questions,atoi(buf)-1);
}
}
void deleteQuestion(Question questions[MAX_QUEST],int *numQuestions)
{
int done=FALSE,i;
char buf[MAX_LINE_LENGTH];
printf("Which question do you wish to delete?(1-%d) ",*numQuestions);
printf("Or 0 for none\n");
while(!done)
{
scanf("%s",buf);
if(isdigit(buf[0]) && (atoi(buf) >= 0) && (atoi(buf) <= (*numQuestions)))
done=TRUE;
else
printf("Please enter a number between 0 and %d.\n",*numQuestions);
}
if (atoi(buf) !=0)
{
for(i=atoi(buf)-1;i<(*numQuestions)-1;i++)
{
questions[i].type=questions[i+1].type;
questions[i].points=questions[i+1].points;
questions[i].leafs=questions[i+1].leafs;
}
(*numQuestions)=(*numQuestions)-1;
}
}
void modifyQuestions(Question questions[MAX_QUEST],int *numQuestions)
{
int done=FALSE;
char buf[MAX_LINE_LENGTH];
while(!done)
{
printQuestions(questions,*numQuestions);
printModifyQuestionMenu();
scanf("%s",buf);
switch(buf[0])
{
case 'a':
addQuestion(questions,numQuestions);
break;
case 'c':
changeQuestion(questions,*numQuestions);
break;
case 'd':
deleteQuestion(questions,numQuestions);
break;
case 'f':
done=TRUE;
break;
default:
printf("Please enter one of a, c, d, f\n");
break;
}
}
}
int getNumSurveyQuest()
{
int numQuestions=0,done=FALSE;
char buf[MAX_LINE_LENGTH];
printf("Please enter the number of questions on the Survey.\n");
while(!done)
{
scanf("%s",buf);
if(isdigit(buf[0]))
{
numQuestions=atoi(buf);
done=TRUE;
}
else
{
printf("Please enter a number.\n");
}
}
return numQuestions;
}
void getQuestionInfo(Question questions[MAX_QUEST],Flags *flags)
{
int done=FALSE,i;
if (flags->SurveyMode)
{
flags->NumQuestions=getNumSurveyQuest();
for (i=0;i<flags->NumQuestions;i++)
{
questions[i].type=ASSIGNED;
questions[i].points=9;
questions[i].leafs=1;
}
}
else
{
if (flags->NumQuestions!=0)
{
printQuestions(questions,flags->NumQuestions);
if (!wantToChangeQuestions())
return;
}
else
{
printQuestionMenu();
while(!done)
if (getNewQuestion(questions,flags->NumQuestions))
flags->NumQuestions++;
else
done=TRUE;
}
modifyQuestions(questions,&(flags->NumQuestions));
}
}
void getInfo(FILE ** outputFile,FILE **scantron,
Question questions[MAX_QUEST],Flags *flags)
{
char filename[MAX_LINE_LENGTH];
getClassInfo(flags,scantron);
sprintf(filename,"records/scorer.output.%d",flags->SetId);
switch(openOutputFile(filename,outputFile))
{
case SCO_FATALERROR:
exit (E_OPENOUTPUT);
break;
case SCO_NEW:
initValues(questions,flags);
break;
case SCO_EXIST:
getPreviousValues(*outputFile,questions,flags);
break;
default:
fprintf(stderr,"openOutputFile returned an invalid code. Dying\n");
exit(E_OPENOUTPUTRETURN);
break;
}
getFlags(flags);
getQuestionInfo(questions,flags);
}
void saveInfo(FILE *outputFile,Question questions[MAX_QUEST],Flags *flags)
{
char configLine[CONFIG_LINE_LENGTH+2],buf[MAX_LINE_LENGTH],
buf2[MAX_LINE_LENGTH],logname[MAX_LINE_LENGTH];
int i;
for(i=0;i<flags->NumQuestions;i++)
{
buf[3*i]=questions[i].type;
buf[3*i+1]=((char)questions[i].points)+'0';
buf[3*i+2]=((char)questions[i].leafs)+'0';
}
buf[3*i]='\0';
buf2[0]=((char)flags->CheckPIN)+'0';
buf2[1]=((char)flags->AnonMode)+'0';
buf2[2]=((char)flags->CheckSpaces)+'0';
buf2[3]=((char)flags->SurveyMode)+'0';
buf2[4]=((char)flags->SurveyHeader)+'0';
buf2[5]=((char)flags->Pause)+'0';
buf2[6]=((char)flags->IdFormat)+'0';
buf2[7]=((char)flags->CheckMultipleMarks)+'0';
buf2[8]=((char)flags->QueryAboutPID)+'0';
buf2[9]=((char)flags->log)+'0';
buf2[10]='\0';
sprintf(configLine,"%s %d %d %s %f %s",flags->Class,flags->SetId,
flags->NumQuestions,buf2,flags->PauseTime,buf);
for(i=strlen(configLine);i<CONFIG_LINE_LENGTH;i++)
configLine[i]=' ';
configLine[CONFIG_LINE_LENGTH]='\n';
configLine[CONFIG_LINE_LENGTH+1]='\0';
rewind(outputFile);
fprintf(outputFile,configLine);
if(flags->log)
{
sprintf(logname,"records/scorer.log.%d",flags->SetId);
flags->logFile=fopen(logname,"w");
if (flags->logFile == NULL)
{
fprintf(stderr,"Unable to open the logFile %s\n",logname);
exit(E_LOGERROR);
}
}
}
void logMultipleAnon(PIDPINlist PIDandPINlist[MAX_SECTION_SIZE],
int matches[MAX_PID_MATCHES],Student* student,
Flags* flags,int maxTotal,int total[MAX_PID_MATCHES])
{
int i;
fprintf(flags->logFile,"#Multiple matching PINs for PID %s :",
student->answerPID);
for(i=0;i<MAX_PID_MATCHES;i++)
{
if (matches[i]==-1) break;
fprintf(flags->logFile," %s score: %d,",
PIDandPINlist[matches[i]].PID,total[i]);
}
flags->loggedErrors++;
fprintf(flags->logFile," picked: %s, serialNumber: %s\n",
PIDandPINlist[matches[maxTotal]].PID,student->serialNumber);
fprintf(flags->logFile,"%s",student->origString);
}
void logError(Student *student,Flags *flags,int errorCode)
{
flags->loggedErrors++;
student->error=1;
switch(errorCode)
{
case LOG_NOPINFOUND:
fprintf(flags->logFile,"#In Anonymous Mode no Student ID could be found for the PIN encoded, PIN=%s (not graded)",student->PIN);
break;
case LOG_PINWRONG:
if (flags->AnonMode)
fprintf(flags->logFile,"#The coded PIN had errors (not graded)");
else
fprintf(flags->logFile,"#The coded PIN had errors, assumed zero for bad responses");
break;
case LOG_STUDENTNOTEXIST:
fprintf(flags->logFile,"#The Student ID %s was not found in the classl file(not graded)",student->answerPID);
break;
case LOG_PINNOTMATCH:
fprintf(flags->logFile,"#The student coded an incorrect PIN(%s) for the specified PID(%s) using the classl PIN, %04d",student->PIN,student->answerPID,student->classlPIN);
break;
case LOG_BADPID:
fprintf(flags->logFile,"#The coded Student ID(%s) was not found in the classl file (not graded)",student->answerPID);
break;
case LOG_BADPIN:
fprintf(flags->logFile,"#The coded PIN (%s) was incorrect(notGraded)",student->PIN);
break;
case LOG_SPACES:
fprintf(flags->logFile,"#The student had blank answers");
break;
case LOG_MULTIPLEMARKS:
fprintf(flags->logFile,"#The student had multiple marks on single mark questions");
break;
default:
fprintf(flags->logFile,"#And unknown error %d occured with this student",errorCode);
break;
}
fprintf(flags->logFile," serialNumber: %s.\n",student->serialNumber);
}
/* stolen from allpin.c and modified by Guy Albertelli*/
int buildPIDandPINlist(int setId, PIDPINlist PIDandPINlist[MAX_SECTION_SIZE] )
{
int i=0,numStudents;
T_student *curStudent,*headStudent;
printf("Building lists of CapaIDs and PIDs\n");
numStudents=capa_get_section(&headStudent, 0);
curStudent=headStudent;
for(i=0;curStudent;curStudent=curStudent->s_next,i++)
{
strcpy(PIDandPINlist[i].PID,curStudent->s_sn);
PIDandPINlist[i].PIN=capa_PIN(curStudent->s_sn,setId,0);
}
free_students(headStudent);
printf("\nDone\n");
return numStudents;
}
int getForm(Student **newStudent,FILE *scantron,
Question questions[MAX_QUEST],Flags *flags)
{
char buffer[MAX_LINE_LENGTH];
char *eof;
int i=0,h=0,j=0,q=0,space=0,found,stepsize,pin,result=0,multiplemarks=0;
int done=FALSE,pinWrong=FALSE;
static int formNumber;
char * array;
if (flags->Pause)
usleep(flags->PauseTime*1000000);
while(!done)
{
eof=fgets(buffer,MAX_LINE_LENGTH,scantron);
if (eof==NULL) return GF_EOF;
if (buffer[0]!='#') done=TRUE;
}
flags->linesRead++;
if (!flags->log)
printf("The Next line is:\n%s\n",buffer);
#ifdef DEBUG
printf("Interpreting the line.\n");
#endif
*newStudent=(Student *)malloc(sizeof(Student));
if (flags->SurveyMode)
/* assign a unique student number since there isn't one on the sheet*/
switch(flags->IdFormat)
{
case ANUMBER_FORMAT:
sprintf((*newStudent)->answerPID,"a%08d",formNumber++);
break;
case SOC_SEC_FORMAT:
sprintf((*newStudent)->answerPID,"%09d",formNumber++);
break;
default:
fprintf(stderr,"Invalid IdFormat data in interpretForm,%d\n",
flags->IdFormat);
exit(E_INVALIDIDFORMAT);
break;
}
else
strncpy((*newStudent)->answerPID,&buffer[56],9);
(*newStudent)->answerPID[9]='\0';
strncpy((*newStudent)->Name,&buffer[40],16);
(*newStudent)->Name[16]='\0';
strncpy((*newStudent)->serialNumber,&buffer[3],6);
(*newStudent)->serialNumber[6]='\0';
strncpy((*newStudent)->origString,buffer,SCAN_INPUT_LENGTH);
(*newStudent)->origString[SCAN_INPUT_LENGTH]='\0';
(*newStudent)->error=0;
/* i is the current position in buffer and h is the current question*/
for(i=0;i<flags->NumQuestions;i++)
{
array=LETTER;
stepsize=2;
switch(questions[i].type)
{
case ASSIGNED:
case SINGLE_DIGIT:
/*the first 5 are special for Anon mode, only first 4 for
*otherwise
*/
if (flags->AnonMode)
if (i > 4)
array=NUMBER;
else
if (i > 3)
array=NUMBER;
case ONE_OUT_OF_8:
found=0;
for(j=(i*10)+76;j<((i+1)*10)+76;j++)
{
if (buffer[j]=='1')
{
h=j;
found++;
}
}
if (found > 1)
{
(*newStudent)->Answers[i][0]=' ';
multiplemarks++;
}
if (found < 1)
{
(*newStudent)->Answers[i][0]=' ';
space++;
}
if (found == 1)
(*newStudent)->Answers[i][0]=array[h-(i*10+76)];
(*newStudent)->Answers[i][1]='\0';
break;
case GLE:
stepsize=3;
case TF:
for(j=0; j<questions[i].leafs; j++)
{
found=0;
for(h = (i*10+76)+j*stepsize; h<(i*10+76)+(j+1)*stepsize; h++)
{
if (buffer[h]=='1')
{
q=h;
found++;
}
if (found > 1)
{
(*newStudent)->Answers[i][j]=' ';
multiplemarks++;
}
if (found < 1)
{
(*newStudent)->Answers[i][j]=' ';
space++;
}
if (found == 1)
(*newStudent)->Answers[i][j]=array[q-(i*10+76)];
}
}
(*newStudent)->Answers[i][questions[i].leafs]='\0';
break;
case N_OUT_OF_M:
case STRING_MATCH:
found=0;
for(j=(i*10)+76;j<((i+1)*10)+76;j++)
{
if (buffer[j]=='1')
{
(*newStudent)->Answers[i][found]=array[j-(i*10+76)];
found++;
}
}
if (found==0) space++;
(*newStudent)->Answers[i][found]='\0';
break;
default:
fprintf(stderr,"Invalid question type %c for question %d in Interpret form.\n Dying\n",questions[h].type,h);
exit(E_INTREPRETFORM);
break;
}
}
pin=0;
for(i=0;i<4;i++)
{
pin*=10;
switch((*newStudent)->Answers[i][0])
{
case 'A': pin+=1;break;
case 'B': pin+=2;break;
case 'C': pin+=3;break;
case 'D': pin+=4;break;
case 'E': pin+=5;break;
case 'F': pin+=6;break;
case 'G': pin+=7;break;
case 'H': pin+=8;break;
case 'I': pin+=9;break;
case 'J': pin+=0;break;
case ' ':
default:
if (!flags->log)
fprintf(stderr,"Garbage answer '%c' for PIN question %d",
(*newStudent)->Answers[i][0],i);
result|=GF_PINWRONG;
pinWrong=TRUE;
pin+=0;break;
}
}
if (pinWrong && flags->log)
logError((*newStudent),flags,LOG_PINWRONG);
sprintf((*newStudent)->PIN,"%04d",pin);
if (space!=0) result|=GF_SPACES;
if (multiplemarks!=0) result|=GF_MULTIPLEMARKS;
return result;
}
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;
}
int surveyQuestion(Question questions[MAX_QUEST],int questionIndex,
Problem_t *problem,Student *student,Flags* flags)
{
int numRight=0;
switch(questions[questionIndex].type)
{
case ASSIGNED:
if (!flags->log)
printf("The student responded with %s\n",student->Answers[questionIndex]);
if (isspace(student->Answers[questionIndex][0]))
numRight=0;
else
numRight=(int)(student->Answers[questionIndex][0]-'0');
break;
case ONE_OUT_OF_8:
case GLE:
case TF:
case SINGLE_DIGIT:
case N_OUT_OF_M:
case STRING_MATCH:
default:
fprintf(stderr,"Illegal question type while in SurveyMode, %c.\nDying.\n",
questions[questionIndex].type);
exit(E_UNKNOWN_QTYPE);
break;
}
return numRight;
}
long getScorerEntry(FILE *outputFile,char *PID)
{
char oneline[MAX_LINE_LENGTH],fmtbuf[MAX_LINE_LENGTH],
studentNumber[MAX_STUDENT_NUMBER];
int done=FALSE,found=FALSE,offset=0,len=0,next_r=0;
rewind(outputFile);
sprintf(fmtbuf,"%%%dc",MAX_STUDENT_NUMBER);
while(!done)
{
done=!fgets(oneline,MAX_LINE_LENGTH-1,outputFile);
len=strlen(oneline);
if (!done)
{
sscanf(oneline,fmtbuf,studentNumber);
if (strncasecmp(studentNumber,PID,MAX_STUDENT_NUMBER)==0)
{
next_r=ftell(outputFile);
offset = next_r-len;
done=TRUE;
found=TRUE;
}
}
else
{
fseek(outputFile,0L,SEEK_END);
offset=ftell(outputFile);
fseek(outputFile,-1L,SEEK_END);
while (fgetc(outputFile)=='\n')
{
offset--;
fseek(outputFile,offset,SEEK_SET);
}
offset= offset+2;
found=FALSE;
done=TRUE;
}
}
if(!found) offset=-offset;
return offset;
}
void setScorerEntry(FILE * outputFile,char* answerPID,char* name,
char* answers,int score, int section,
char* answerstring,char* questionPID,
char* serialNumber,int offset)
{
int len=0;
char buf[MAX_LINE_LENGTH];
rewind(outputFile);
sprintf(buf,"%s %-30s %s %3d %2d %s %s %s\n",answerPID,name,answers,
score,section,answerstring,questionPID,serialNumber);
len=strlen(buf);
fseek(outputFile,abs(offset),0);
if(!fwrite(buf,len,1,outputFile))
fprintf(stderr,"Failed write.\n");
}
void saveForm(Student *student,FILE *outputFile,
Question questions[MAX_QUEST],Flags *flags)
{
int result,capaQuestions,questionIndex,numRight,total=0;
int offset;
Problem_t *curProblem,*headProblem;
char answerstring[MAX_LINE_LENGTH],grade[MAX_LINE_LENGTH];
char buf[MAX_LINE_LENGTH];
T_student capaStudent;
if (!flags->SurveyMode)
{
switch(capa_get_student(student->answerPID, &capaStudent))
{
case 1: break;
case 0:
if (flags->log)
logError(student,flags,LOG_STUDENTNOTEXIST);
else
{
fprintf(stderr,"Student %s was not found.\n",student->answerPID);
printf("Type start to continue");
scanf("%s",buf);
}
return;
break;
case -1:
fprintf(stderr,"Unable to find the classl file while grading\n");
exit(E_CAPA_GET_STUDENT); break;
default:
fprintf(stderr,"Unknow error from capa_get_student while grading\n");
exit(E_CAPA_GET_STUDENT); break;
}
result=capa_parse(flags->SetId,&headProblem,student->questionPID,
&capaQuestions);
curProblem=headProblem;
if (result==0 || result == -1)
{
fprintf(stderr,"The Parse failed: %d\nDying\n",result);
exit(E_PARSER);
}
else if (result != flags->NumQuestions)
{
fprintf(stderr,"The parser found %d questions, there were supposed to be %d questions.\nDying\n",result,flags->NumQuestions);
exit(E_PARSER_DIFFERENT);
}
for(questionIndex=0;questionIndex<flags->NumQuestions;questionIndex++)
{
numRight=gradeQuestion(questions,questionIndex,curProblem,
student,flags);
total+=numRight;
grade[questionIndex]='0'+(char)numRight;
curProblem=curProblem->next;
}
grade[questionIndex]='\0';
printf("Total right for student %s is %d\n\n",capaStudent.s_nm,total);
free_problems(headProblem);
}
else
{
strcpy(capaStudent.s_nm,"Unknown ");
capaStudent.s_sec=0;
headProblem=curProblem=NULL;
for(questionIndex=0;questionIndex<flags->NumQuestions;questionIndex++)
{
numRight=surveyQuestion(questions,questionIndex,curProblem,
student,flags);
total+=numRight;
grade[questionIndex]='0'+(char)numRight;
}
grade[questionIndex]='\0';
}
answerstring[0]='\0';
for(questionIndex=0;questionIndex<flags->NumQuestions;questionIndex++)
strcat(answerstring,student->Answers[questionIndex]);
offset=getScorerEntry(outputFile,student->answerPID);
setScorerEntry(outputFile,student->answerPID,capaStudent.s_nm,grade,
total,capaStudent.s_sec,answerstring,student->questionPID,
student->serialNumber,offset);
}
int getScore(Student *student,Question questions[MAX_QUEST],Flags *flags,
char* grade,int gradingMethod)
{
int score=0,numRight=0,tempScore,i,leafs,points,unit;
for(i=0;i<flags->NumQuestions;i++)
{
switch(questions[i].type)
{
case ONE_OUT_OF_8:
case SINGLE_DIGIT:
numRight= (int) (grade[i]-'0');
score+=numRight*questions[i].points;
break;
case STRING_MATCH:
/*for STRING_MATCH the score is stroed as the NumRight*/
numRight= (int) (grade[i]-'0');
score+=numRight;
break;
case GLE:
case TF:
case N_OUT_OF_M:
numRight=(int) (grade[i]-'0');
leafs=questions[i].leafs;
points=questions[i].points;
unit=(int)ceil((double)points/(double)leafs);
if (unit==0) unit=points;
switch (gradingMethod)
{
case CAPA_METHOD:
tempScore=points-(2*unit*(leafs-numRight));
break;
case LENIENT_METHOD:
tempScore=points-(unit*(leafs-numRight));
break;
case STRICT:
if (numRight==leafs) tempScore=points;
else tempScore=0;
break;
default:
fprintf(stderr,"Unknown grading Method. %d\n",gradingMethod);
exit(E_GRADINGMETHOD);
break;
}
if (tempScore<0)
tempScore=0;
score+=tempScore;
break;
case ASSIGNED:
numRight= (int) (grade[i]-'0');
score+=numRight;
break;
default:
fprintf(stderr,"Unknown question type %c\n",questions[i].type);
break;
}
}
return score;
}
void saveAnonForm(Student *student,FILE *outputFile,
Question questions[MAX_QUEST],
PIDPINlist PIDandPINlist[MAX_SECTION_SIZE],
Flags *flags)
{
int i,j=0,matches[MAX_PID_MATCHES],done=FALSE;
int result,capaQuestions,questionIndex,numRight,total[MAX_PID_MATCHES];
int offset,maxTotal=0,score,correctID=-1;
Problem_t *curProblem,*headProblem;
char answerstring[MAX_LINE_LENGTH],buf[MAX_LINE_LENGTH],
grade[MAX_PID_MATCHES][MAX_LINE_LENGTH],buffer[MAX_LINE_LENGTH];
T_student capaStudent;
if (!flags->log)
printf("Attempting to find a student with CAPA PIN %s.\n",student->PIN);
for(i=0;i<flags->NumOfStudents;i++)
{
if (atoi(student->PIN)==PIDandPINlist[i].PIN)
{
matches[j]=i;
j++;
}
}
matches[j]=-1;
switch(j)
{
case 0:
if(flags->log)
logError(student,flags,LOG_NOPINFOUND);
else
{
printf("No match for PIN %s\n",student->PIN);
printf("The current form's PIN is incorrect.\n");
printf("Please type start to continue.\n");
scanf("%s",buf);
}
return;
break;
case 1:
if (!flags->log)
printf("Only one match assuming PID %s\n",
PIDandPINlist[matches[0]].PID);
strcpy(student->questionPID,PIDandPINlist[matches[0]].PID);
saveForm(student,outputFile,questions,flags);
return;
break;
default:
break;
}
/* Only get here if there is more than one valid PID*/
if (!flags->log)
printf("Found %d matches.\n",j);
maxTotal=-1;
for(i=0;i<MAX_PID_MATCHES;i++)
{
total[i]=0;
if (matches[i]==-1) break;
switch(capa_get_student(student->answerPID, &capaStudent))
{
case 1: break;
case 0:
if (flags->log)
logError(student,flags,LOG_STUDENTNOTEXIST);
else
{
fprintf(stderr,"Student %s was not found.\n",student->answerPID);
printf("Type start to continue");
scanf("%s",buf);
}
return;
break;
case -1:
fprintf(stderr,"Unable to find the classl file while grading\n");
exit(E_CAPA_GET_STUDENT); break;
default:
fprintf(stderr,"Unknown error from capa_get_student while grading\n");
exit(E_CAPA_GET_STUDENT); break;
}
strcpy(student->questionPID,PIDandPINlist[matches[i]].PID);
result=capa_parse(flags->SetId,&headProblem,student->questionPID,
&capaQuestions);
curProblem=headProblem;
if (result==0 || result == -1)
{
fprintf(stderr,"The Parse failed: %d\nDying\n",result);
exit(E_PARSER);
}
else if (result != flags->NumQuestions)
{
fprintf(stderr,"The parser found %d questions, there were supposed to be %d questions.\nDying\n",result,flags->NumQuestions);
exit(E_PARSER_DIFFERENT);
}
for(questionIndex=0;questionIndex<flags->NumQuestions;questionIndex++)
{
numRight=gradeQuestion(questions,questionIndex,curProblem,
student,flags);
if (questionIndex==4)
if (numRight==1)
correctID=i;
total[i]+=numRight;
grade[i][questionIndex]='0'+(char)numRight;
curProblem=curProblem->next;
}
if (total[i] > total[maxTotal]) maxTotal=i;
grade[i][questionIndex]='\0';
/*printf("Total right for PID %s is %d\n",PIDandPINlist[matches[i]].PID,
total[i]);*/
free_problems(headProblem);
}
if (correctID!=-1)
{
answerstring[0]='\0';
for(questionIndex=0;questionIndex<flags->NumQuestions;questionIndex++)
strcat(answerstring,student->Answers[questionIndex]);
offset=getScorerEntry(outputFile,student->answerPID);
printf("Total right for student %s is %d\n\n",capaStudent.s_nm,
total[correctID]);
setScorerEntry(outputFile,student->answerPID,capaStudent.s_nm,
grade[correctID],total[correctID],capaStudent.s_sec,
answerstring,student->questionPID,student->serialNumber,
offset);
return;
}
if (!flags->QueryAboutPID && flags->log)
{
logMultipleAnon(PIDandPINlist,matches,student,flags,maxTotal,total);
answerstring[0]='\0';
for(questionIndex=0;questionIndex<flags->NumQuestions;questionIndex++)
strcat(answerstring,student->Answers[questionIndex]);
offset=getScorerEntry(outputFile,student->answerPID);
printf("Total right for student %s is %d\n\n",capaStudent.s_nm,
total[maxTotal]);
setScorerEntry(outputFile,student->answerPID,capaStudent.s_nm,
grade[maxTotal],total[maxTotal],capaStudent.s_sec,
answerstring,student->questionPID,student->serialNumber,
offset);
}
else
{
while(!done)
{
printf("Please press\n");
for(i=0;i<MAX_PID_MATCHES;i++)
{
if (matches[i]==-1)
break;
printf("%d) for student number %s ",i+1,
PIDandPINlist[matches[i]].PID);
strcpy(student->questionPID,PIDandPINlist[matches[i]].PID);
score=getScore(student,questions,flags,grade[i],
LENIENT_METHOD);
printf(" Lenient: %3d ",score);
score=getScore(student,questions,flags,grade[i],
CAPA_METHOD);
printf(" CAPA: %3d ",score);
score=getScore(student,questions,flags,grade[i],
STRICT);
printf(" Strict: %3d \n",score);
}
scanf("%s",buffer);
if (isdigit(buffer[0]) && (atoi(buffer) < (j+1)) &&
(atoi(buffer) > 0))
{
strcpy(student->questionPID,
PIDandPINlist[matches[atoi(buffer)-1]].PID);
saveForm(student,outputFile,questions,flags);
done=TRUE;
}
}
}
}
int checkForm(Student * student,Flags *flags)
{
int error,pin;
T_student capaStudent;
#ifdef DEBUG
int i,j;
printf("PID:\t%s\nPIN:\t%s\nName:\t%s\n",
student->answerPID,student->PIN,student->Name);
for(i=0,j=0;i<flags->NumQuestions;i++)
{
printf("Answer %d: %s\n",i+1,student->Answers[i]);
}
#endif /*DEBUG*/
error=capa_get_student(student->answerPID, &capaStudent);
switch(error)
{
case 1:
if (!flags->log)
printf("The current student is %s from section %d\n",
capaStudent.s_nm,capaStudent.s_sec);
break;
case 0:
if (!flags->log)
{
printf("Error Finding the student.\n");
printf("The Scantron reported the PID:%s\n",student->answerPID);
printf("But this was not found in the classl file.\n");
}
return CF_STID;
break;
case -1:
return CF_CLASSL;
break;
default:
fprintf(stderr,"capa_get_student returned an invalid result");
fprintf(stderr,"in CheckForm.\n Error=%d. Dying\n",error);
exit(E_CAPA_GET_STUDENT);
break;
}
if (flags->CheckPIN && !flags->AnonMode)
{
pin=capa_PIN(student->answerPID,flags->SetId,0);
if (pin!=atoi(student->PIN))
{
if (flags->log)
{
student->classlPIN=pin;
logError(student,flags,LOG_PINNOTMATCH);
sprintf(student->PIN,"%04d",pin);
}
else
{
printf("There is an error with the students PIN:\n");
printf("The Scantron reported:%s, The Classl file has:%d\n",
student->PIN,pin);
fprintf(stderr,"If you wish to use what the Classl file reports\n");
fprintf(stderr,"enter y, else enter n.\n");
if (getYesOrNo()==YES)
sprintf(student->PIN,"%04d",pin);
else
return CF_PIN;
}
}
}
return CF_NOERROR;
}
int handleCheckForm(Student *student,FILE *outputFile,
PIDPINlist PIDandPINlist[MAX_SECTION_SIZE],
Question questions[MAX_QUEST],Flags *flags)
{
int done=FALSE,error;
char buf[MAX_LINE_LENGTH];
switch(error=checkForm(student,flags))
{
case CF_STID:
if (flags->log)
logError(student,flags,LOG_BADPID);
else
{
printf("The current form's Student Id is incorrect.\n");
printf("Please type start to continue.\n");
scanf("%s",buf);
}
break;
case CF_CLASSL:
fprintf(stderr,"The classl file was not found in the");
fprintf(stderr," current directory.\n");
fprintf(stderr,"Please try again.\n");
done=TRUE;
break;
case CF_PIN:
if (flags->log)
logError(student,flags,LOG_BADPIN);
else
{
fprintf(stderr,"The current form's PIN is incorrect.\n");
fprintf(stderr,"Please type start to continue.\n");
scanf("%s",buf);
}
break;
case CF_NOERROR:
printf("Grading and Saving Student %s Serial#: %s\n",
student->answerPID,student->serialNumber);
if (flags->AnonMode)
saveAnonForm(student,outputFile,questions,PIDandPINlist,flags);
else
{
strcpy(student->questionPID,student->answerPID);
saveForm(student,outputFile,questions,flags);
}
break;
default:
fprintf(stderr,"Unimplemented error in checkForm %d\n",error);
exit(E_CHECKFORM);
break;
}
return done;
}
int handleGetFormStatus(int status,Student *student,FILE *outputFile,
PIDPINlist PIDandPINlist[MAX_SECTION_SIZE],
Question questions[MAX_QUEST],Flags *flags)
{
int done=FALSE,save=TRUE;
if (status & GF_SPACES)
if (flags->CheckSpaces)
{
if (flags->log)
logError(student,flags,LOG_SPACES);
else
{
printf("The current form appears to have some questions left\n");
printf("blank. Please enter yes if you wish to continue \n");
printf("grading of this form.\n");
if (getYesOrNo()==YES)
;
else
save=FALSE;
}
}
if(status & GF_MULTIPLEMARKS)
if (flags->CheckMultipleMarks)
{
if (flags->log)
logError(student,flags,LOG_MULTIPLEMARKS);
else
{
printf("The current form appears to have some questions with\n");
printf("multiple marks on lines that should have only one.\n");
printf("Please enter yes if you wish to continue grading of this form.\n");
if (getYesOrNo()==YES)
;
else
save=FALSE;
}
}
if (status == GF_EOF)
done=TRUE;
if ((status & GF_PINWRONG) && flags->AnonMode) return done;
if (!done && save)
if (!flags->SurveyMode)
{
#ifdef DEBUG
printf("Checking form.\n");
#endif
done=handleCheckForm(student,outputFile,PIDandPINlist,questions,
flags);
}
else
if (flags->AnonMode)
saveAnonForm(student,outputFile,questions,PIDandPINlist,flags);
else
{
strcpy(student->questionPID,student->answerPID);
saveForm(student,outputFile,questions,flags);
}
return done;
}
void processForms(FILE *outputFile, FILE *scantron,
Question questions[MAX_QUEST], Flags *flags)
{
int done=FALSE;
int status;
Student *student=NULL;
PIDPINlist PIDandPINlist[MAX_SECTION_SIZE];
if (flags->AnonMode)
{
flags->NumOfStudents=buildPIDandPINlist(flags->SetId,PIDandPINlist);
if (flags->NumOfStudents==0)
{
fprintf(stderr,"buildPIDandPINlists returned 0 students.");
exit(E_BUILDPIDPIN);
}
}
while(!done)
{
#ifdef DEBUG
printf("Reading in a new form.\n");
#endif
status=getForm(&student,scantron,questions,flags);
done=handleGetFormStatus(status,student,outputFile,PIDandPINlist,
questions,flags);
if (student != NULL)
{
if (student->error)
fprintf(flags->logFile,"%s",student->origString);
free(student);
}
student=NULL;
}
}
void printResults(Flags* flags)
{
printf("Number scanned %d, number errors logged %d\n.",
flags->linesRead,flags->loggedErrors);
}
int main(int argc, char **argv)
{
FILE *outputFile;
Question questions[MAX_QUEST];
Flags flags;
FILE *scantron;
Parsemode_f=ASCII_MODE;
flags.linesRead=0;
flags.loggedErrors=0;
initScreen();
getInfo(&outputFile,&scantron,questions,&flags);
saveInfo(outputFile,questions,&flags);
processForms(outputFile,scantron,questions,&flags);
printResults(&flags);
return 0;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>