/* AUTHOR: Jordi Saludes DATE: 12/9/1996 FILE: knd.c kndecode - Decoder of knapsack tests answers. SYNOPSIS kndecode [-i] [-apSGI] filename1 [filename2] DESCRIPTION kndecode decodes page totals for knapsack tests. kndecode reads first the exam description, then the students identifiers and answers and returns grades, decoded answers and other information. When filename2 is given, filename1 contains the exam description (usually a .ans file) and filename2 contains the students data and answers. When only one file name is given, filename1 contains first the exam description and then, after a blank line, the students data. filename2 can be `-', namely the standard input. Exam description The exam description is usally written by the TeX run of exam file into a .ans file. Lines of such desciption are \opts q p r: Question number q has p options. Option number r is the right one. \pagebot q: Question q is the last one in current page. \Key k d: k is the key for the test and d is the detection factor. Data lines Each line contains identifier, page totals (and possibly version number) of a student. Fields are separated by spaces. First field must be the identifier (long int) of student, next ones are the consecutive page totals. However if one of these fields f is negative, it is assumed that it represents a new version number instead of a page total. Version number is -f from now on. If no options are given the student identifier is not expected. OPTIONS i Read incidences. Second field must be an octal number standing for incidences ocurred in the pre-processing of the exam data file. a Return answers of exam, separated by tabs. p Return plain (decoded) page totals, for archiving purposes. S Return the number of right, wrong and null answers. G Return grade. Right answer means +1, null answer means 0, value of wrong answers are adjusted to have 0 expectation when questions are answered picking answers randomly. Modify routine "qualifica" to change grading. I Output incidences. Input incidences from pre-processing (when i option is given) are OR-ed with incidences generated by kndecode and returned. None All information returned by the a, p, S or G options is displayed in more human-readable form. No student identifier is expected as first field. EXAMPLES kndecode foo.ans - -38353 17942344 (Version number) (Page 1 total) kndecode -G foo.ans - (Only grade) 1001 -38353 17942344 674532 (IDentifier) (V) (P1) (P2) kndecode -i -GI foo.ans - (Grade and output incidences) 1001 2 -38353 17942344 674532 (ID) (Incid.) (V) (P1) (P2) */ #include #include #include #define NSDF 1 /* Page total is not a multiple of df */ #define BVER 2 /* Bad version number: Not inversible */ #define BCNT 4 /* Bad control number. From pre-processing */ #define DUPR 8 /* Duplicated record. From pre-processing */ #define BDEC 16 /* Bad decoding */ #define MQNS 100 /* Max number of questions */ #define MPAGS 10 /* Max number of pages in a test */ #define GRADE 1 #define PLAIN 2 #define STAT 4 #define ANSW 8 #define IIND 16 #define OIND 32 #define NSDF_str "%s: %ld is not a multiple of %hd\n" #define BVER_str "%s: %ld has no inverse\n" #define BDEC_str "%s: Bad decoding for %ld\n" #define BFMT_str "%s: Bad format file\n" #define UNKO_str "%s: Unknown option\n" typedef struct {short int nopt,marca,ref; long int w;} question; question qn[MQNS]; short int npag,df,nq; short int pb[MPAGS]; /* ref[MQNS],nopt[MQNS],marca[MQNS],pb[MPAGS]; */ long int key; /* w[MQNS]; */ int getOptions(int argc, char *argv[], FILE **dataF, short *opts); int aplana(long *pla, long a, long s, long modul); int inverteix(long *in, long b, long key); int deco(long v, long s, question r[],short n,long *pla); float qualifica(short *n,short *b, short *m); int main(argc, argv) int argc; char *argv[]; { FILE *dataF; int errs; short int i,j,incid,opts; short int bons,mals,nuls; long int dni,suma,versio=1L,spla; float nota; int c; if(getOptions(argc,argv,&dataF,&opts)==0) return(1); while(1) { incid=0; bons=mals=nuls=0; nota=0.0; if(opts) { if(fscanf(dataF,"%ld",&dni)==EOF) break; if (opts&IIND && fscanf(dataF,"%ho",&incid)==EOF) break; printf("%ld",dni); } for(i=0;i0) { u1=t1; u2=t2; u3=t3; } else { v1= v-t1; v2= -u-t2; v3= -t3; } t1=u1-v1; t2=u2-v2; t3=u3-v3; if (t1<0) { t1+=v; t2-=u;} if (t3!=0) goto y3; *in= u1; return 0; } /** Return grade. Give also the nuwer of ** right, wrong and null answers. **/ float qualifica(short *n,short *b,short *m) { short int i; float nota=0.0; (*n)= (*b)= (*m)= 0; for(i=0; i>=1) if(v&1) sp=(sp+s)%key; *pla=sp; for (i=n-1; i>=0; i--) { if ((res[i].marca=sp/res[i].w)>res[i].nopt) return(1); sp= sp%res[i].w; } return(0); } /** Get the options in the command line ** **/ int getOptions(int argc, char *argv[], FILE **dataF, short int *opts) { short int k,i,j,na,cref; long int m=1; int errs, rcs; char opt, rec[50]; *dataF=NULL; if (argc<=1) return(0); *opts=0; for (k=1;k0); for(j=0,i=1; i<=npag; i++) for(m=1; j