Annotation of capa/capa51/pProj/capaCommon.c, revision 1.1
1.1 ! albertel 1: /* =||>|===================== capaCommon.c =====================|<||= */
! 2: /* created 1994 by Isaac Tsai */
! 3: /* 1994, 1995, 1996, 1997, 1998, 1999 copyrighted by Isaac Tsai */
! 4: /* TODO: restructure capa_check_ans*() calls into one */
! 5: /* =||>|===================== capaCommon.c =====================|<||= */
! 6: #include <ctype.h>
! 7: #if defined(__sun) || defined(linux) || defined(__alpha) || defined(hpux) || defined(AIX) || defined(IRIX)
! 8: #include <unistd.h> /* lockf() */
! 9: #endif
! 10: #include <sys/types.h>
! 11: #include <sys/stat.h>
! 12: #include <fcntl.h>
! 13: #include "capaParser.h"
! 14: #include "capaToken.h"
! 15: #include "capaCommon.h"
! 16: #include "ranlib.h"
! 17:
! 18:
! 19: /*----------------------------------------------------------*/
! 20: /* flock() in SUN is in BSD compatibility lib */
! 21: /* #include <sys/file.h> */
! 22: /*----------------------------------------------------------*/
! 23:
! 24: int yyparse();
! 25: extern FILE *yyin;
! 26: extern void yyrestart();
! 27:
! 28: /*----------------------------------------------------------*/
! 29: /* RETURN: -1 file error */
! 30: /* 0 success */
! 31: /* INPUT: if section == 0, for all students in class */
! 32: /* set : 1, 2, 3, ... */
! 33: /* prob: 1, 2, 3, ... */
! 34: /*----------------------------------------------------------*/
! 35: int
! 36: capa_excuse(int set,int prob,int section)
! 37: {
! 38: int nq;
! 39: T_header header;
! 40: T_entry entry;
! 41: T_student *student_p, *s1_p;
! 42: char tmp_number[MAX_STUDENT_NUMBER+1];
! 43: long offset;
! 44: int num_students;
! 45:
! 46: /* Calculate parameters */
! 47: if (capa_get_header(&header,set)) return (-1);
! 48: sscanf(header.num_questions,"%d", &nq);
! 49: capa_mfree(header.weight);
! 50: capa_mfree(header.partial_credit);
! 51:
! 52: if( ( prob > nq ) || (section < 0 ) || (section > MAX_SECTION_COUNT) ) return (-1);
! 53: num_students= 0;
! 54: if ( (num_students = capa_get_section(&student_p, section))== -1 ) return (-1);
! 55: for ( s1_p = student_p ; s1_p ; s1_p = (s1_p->s_next)) {
! 56: sprintf(tmp_number,"%s",s1_p->s_sn);
! 57: offset = capa_get_entry(&entry,tmp_number,set);
! 58: if(offset < 0 ) offset = -offset;
! 59: switch(entry.answers[prob-1]) {
! 60: case '-': entry.answers[prob-1] = 'E'; break;
! 61: case 'N': entry.answers[prob-1] = 'E'; break;
! 62: case 'n': entry.answers[prob-1] = 'e'; break;
! 63: default : break;
! 64: }
! 65: capa_set_entry(&entry,tmp_number,set,offset);
! 66: capa_mfree(entry.answers); entry.answers = NULL;
! 67: capa_mfree(entry.tries); entry.tries = NULL;
! 68: }
! 69: free_students(student_p);
! 70: return (0);
! 71: }
! 72:
! 73: /*----------------------------------------------------------*/
! 74: /* Lock file shared */
! 75: /* lock the file specified by file stream pointer sp */
! 76: /*----------------------------------------------------------*/
! 77: int
! 78: flockstream_sh(sp) FILE *sp;
! 79: {
! 80: int fd;
! 81:
! 82: fd = fileno(sp);
! 83:
! 84: #if defined(__sun) || defined(hpux) || defined(AIX)
! 85: return ( lockf(fd,F_LOCK, 0L) );
! 86: #else
! 87: return (flock(fd,LOCK_SH));
! 88: #endif
! 89: }
! 90: /*----------------------------------------------------------*/
! 91: int
! 92: flockstream(sp) FILE *sp;
! 93: {
! 94: int fd;
! 95:
! 96: fd = fileno(sp);
! 97:
! 98: #if defined(__sun) || defined(hpux) || defined(AIX)
! 99: return ( lockf(fd,F_LOCK, 0L) );
! 100: #else
! 101: return (flock(fd,LOCK_EX));
! 102: #endif
! 103: }
! 104: /*----------------------------------------------------------*/
! 105: int
! 106: funlockstream(sp) FILE *sp;
! 107: {
! 108: int fd;
! 109:
! 110: fd = fileno(sp);
! 111:
! 112: #if defined(__sun) || defined(hpux) || defined(AIX)
! 113: return ( lockf(fd,F_ULOCK, 0L) );
! 114: #else
! 115: return ( flock(fd,LOCK_UN) );
! 116: #endif
! 117: }
! 118:
! 119: int
! 120: inquery_a_lock(sp,cmd,type,offset,whence,len)
! 121: FILE *sp;int cmd;off_t offset;int whence;off_t len;
! 122: {
! 123: struct flock lock;
! 124: int fd;
! 125: lock.l_type = type; lock.l_start = offset;
! 126: lock.l_whence = whence; lock.l_len = len;
! 127: fd=fileno(sp);
! 128: return (fcntl(fd,cmd,&lock));
! 129: }
! 130: #define Blocked_Write_Lock(sp) \
! 131: inquery_a_lock(sp,F_SETLK,F_WRLCK,0,0,0)
! 132:
! 133: #define Blocked_Write_Lock(sp) \
! 134: inquery_a_lock(sp,F_SETLK,F_WRLCK,0,0,0)
! 135:
! 136: #define Un_Lock(sp) \
! 137: inquery_a_lock(sp,F_SETLK,F_UNLCK,0,0,0)
! 138:
! 139:
! 140: /*----------------------------------------------------------*/
! 141: /* INPUT: set problem set number */
! 142: /* RETURN: -1 no records/setX.db file or file error */
! 143: /* 0 success */
! 144: /* OUTPUT: header pointer to T_header structure */
! 145: /*----------------------------------------------------------*/
! 146: int
! 147: capa_set_header(header, set) T_header *header;int set;
! 148: {
! 149: FILE *fp;
! 150: char *big_buf=NULL, filename[FILE_NAME_LENGTH], cr=0, oneline[TMP_LINE_LENGTH];
! 151: int nq, len, errcode, fd, item_cnt, exists=1;
! 152: T_header oldheader;
! 153: long orig_size, new_size, big_buf_size;
! 154:
! 155: sprintf(filename,"records/set%d.db",set);
! 156: if ((fp=fopen(filename,"r+"))==NULL) {
! 157: exists=0;
! 158: if ((fp=fopen(filename,"w"))==NULL) { /* create if non-existant */
! 159: /*printf("Error: can't open %s\n",filename);*/ return (-1);
! 160: }
! 161: }
! 162: sscanf(header->num_questions,"%d",&nq);
! 163: /* sprintf(oneline,"%d,%s,%s,%s\n",nq,header->open_date,header->due_date,header->answer_date); */
! 164: sprintf(oneline,"%d\n",nq);
! 165: len = strlen(oneline);
! 166: flockstream(fp); errcode = 0;
! 167:
! 168: if (exists) {
! 169: /*get file size*/
! 170: fseek(fp,0L,SEEK_END);
! 171: orig_size = ftell(fp);
! 172: big_buf_size = orig_size; /*the amt we need to read is less then the file's size*/
! 173: big_buf = capa_malloc(big_buf_size,1);
! 174: fseek(fp,0L,SEEK_SET);
! 175:
! 176: /*read in old header*/
! 177: fscanf(fp,"%d",&nq);
! 178: while ( cr != '\n' && cr != EOF ) { cr=fgetc(fp); }
! 179: oldheader.weight=capa_malloc(nq+1,1);
! 180: oldheader.partial_credit=capa_malloc(nq+1,1);
! 181: if (!fread(oldheader.weight, sizeof(char), nq, fp)) errcode = -2;
! 182: if (EOF==(cr=fgetc(fp))) errcode = -3;
! 183: if (!fread(oldheader.partial_credit, sizeof(char), nq, fp)) errcode = -4;
! 184: if (EOF==(cr=fgetc(fp))) errcode = -5;
! 185: capa_mfree(oldheader.weight);
! 186: capa_mfree(oldheader.partial_credit);
! 187:
! 188: /*read rest of file*/
! 189: item_cnt=fread(big_buf,1,big_buf_size, fp);
! 190: }
! 191:
! 192: /*write new header*/
! 193: fseek(fp,0L,SEEK_SET);
! 194: if (!fwrite(oneline, len, 1, fp)) {errcode = -6;}
! 195: if ( header->weight != NULL ) {
! 196: if (!fwrite((char *)(header->weight), strlen(header->weight), 1, fp)) errcode=-7;
! 197: }
! 198:
! 199: if (EOF==(!fputc('\n', fp))) errcode = -8;
! 200: if (header->partial_credit != NULL) {
! 201: if (!fwrite((char *)(header->partial_credit), strlen(header->partial_credit),
! 202: 1, fp)) { errcode = -9; }
! 203: }
! 204: if (EOF==(!fputc('\n', fp))) errcode = -10;
! 205:
! 206: if (exists) {
! 207: /*write out rest of file*/
! 208: if (item_cnt >= 0 ) {
! 209: big_buf[item_cnt]=0;
! 210: if (!fwrite(big_buf,item_cnt,1,fp) ) errcode= -11;
! 211: new_size = ftell(fp);
! 212: if (new_size < orig_size ) {
! 213: fd = fileno(fp);
! 214: ftruncate(fd,new_size);
! 215: }
! 216: }
! 217: }
! 218:
! 219: fflush(fp);
! 220: funlockstream(fp); fclose(fp);
! 221: if (big_buf!=NULL) capa_mfree(big_buf);
! 222: return (errcode);
! 223: }
! 224:
! 225: /*----------------------------------------------------------*/
! 226: /* INPUT: set problem set number */
! 227: /* RETURN: -1 file error */
! 228: /* 0 success */
! 229: /* OUTPUT: header pointer to T_header structure */
! 230: /* Note: allocates space for the partial_credit and weight */
! 231: /* fields of the passed in header, caller needs to */
! 232: /* eventually free them with capa_mfree */
! 233: /*----------------------------------------------------------*/
! 234: int
! 235: capa_get_header(header, set) T_header *header;int set;
! 236: {
! 237: FILE *fp;
! 238: char filename[FILE_NAME_LENGTH];
! 239: char cr;
! 240: int nq=0, errcode;
! 241:
! 242: sprintf(filename,"records/set%d.db",set);
! 243: if ((fp=fopen(filename,"r"))==NULL) {
! 244: /*printf("Error capa_get_header(): can't open %s\n",filename);*/
! 245: return (-1);
! 246: }
! 247:
! 248: flockstream(fp); errcode = 0;
! 249: fscanf(fp,"%d",&nq);
! 250: cr='\0';
! 251: while ( cr != '\n' && cr != EOF ) { cr=fgetc(fp); }
! 252: header->weight=capa_malloc(nq+1,1);
! 253: header->partial_credit=capa_malloc(nq+1,1);
! 254: if (nq > 0 ) {
! 255: if (!fread(header->weight, sizeof(char), nq, fp)) errcode = -1;
! 256: }
! 257: if (EOF==(cr=fgetc(fp))) errcode = -1;
! 258: if (nq > 0 ) {
! 259: if (!fread(header->partial_credit, sizeof(char), nq, fp)) errcode = -1;
! 260: }
! 261:
! 262: funlockstream(fp); fclose(fp);
! 263: header->weight[nq]='\0'; header->partial_credit[nq]='\0';
! 264: sprintf(header->num_questions,"%d",nq);
! 265: return (errcode);
! 266: }
! 267: /*----------------------------------------------------------*/
! 268: /* ----------- previous version, obsolete as of May 1997
! 269: int
! 270: capa_set_entry(entry, student_number, set, offset)
! 271: T_entry *entry;
! 272: char *student_number;
! 273: int set;
! 274: long offset;
! 275: {
! 276: FILE *fp;
! 277: int errcode=0;
! 278: int len;
! 279: char filename[FILE_NAME_LENGTH];
! 280: char a_line[TMP_LINE_LENGTH];
! 281:
! 282: sprintf(filename,"records/set%d.db",set);
! 283: if ((fp=fopen(filename,"r+"))==NULL) {
! 284: return (-1);
! 285: }
! 286: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
! 287: len = strlen(a_line);
! 288: flockstream(fp);
! 289: fseek(fp,offset,0);
! 290: if (!fwrite(a_line,len,1,fp) ) {
! 291: printf("Error writing data to file\n");
! 292: errcode= (-1);
! 293: }
! 294: fflush(fp);
! 295: funlockstream(fp);
! 296: fclose(fp);
! 297: return (errcode);
! 298: }
! 299: ---------- */
! 300:
! 301: int
! 302: capa_set_entry(entry, student_number, set, offset)
! 303: T_entry *entry;
! 304: char *student_number;
! 305: int set;
! 306: long offset;
! 307: {
! 308: FILE *fp;
! 309: int fd;
! 310: int errcode=0;
! 311: int done, len, new_len, item_cnt;
! 312: long next_r, orig_size, new_size, big_buf_size;
! 313: char filename[FILE_NAME_LENGTH];
! 314: char *a_line, tmpline[TMP_LINE_LENGTH],
! 315: tmp_sn[MAX_STUDENT_NUMBER+1], fmtbuf[SMALL_LINE_BUFFER];
! 316: char *big_buf;
! 317:
! 318: sprintf(filename,"records/set%d.db",set);
! 319: if ((fp=fopen(filename,"r+"))==NULL) {
! 320: /* printf("Error capa_set_entry(): can't open %s\n",filename); */ return (-1);
! 321: }
! 322: /* entry->answers*3 == entry->tries, + fudge factor*/
! 323: a_line=capa_malloc(strlen(entry->tries)*5+MAX_STUDENT_NUMBER,1);
! 324: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
! 325: new_len = strlen(a_line);
! 326: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
! 327: flockstream(fp); /* <==== lock the setX.db file */
! 328: fseek(fp,0L,SEEK_END);
! 329: orig_size = ftell(fp);
! 330: big_buf_size = orig_size + new_len;
! 331: big_buf = capa_malloc(big_buf_size,1);
! 332: fseek(fp,0L,SEEK_SET); /* rewind to beginning of file */
! 333: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* skip weight line, including \n */
! 334: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* hand grading */
! 335: done = 0;
! 336: while(!done) {
! 337: done = !fgets(tmpline,TMP_LINE_LENGTH-1,fp); len = strlen(tmpline);
! 338: if( !done ) {
! 339: sscanf(tmpline,fmtbuf,tmp_sn);
! 340: if( !strncasecmp(tmp_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
! 341: next_r = ftell(fp); offset = next_r - len; done = 1;
! 342: item_cnt=fread(big_buf,1,big_buf_size, fp); /* read remaining lines into buffer */
! 343: if(item_cnt >= 0 ) { /* no error reading remaining lines */
! 344: big_buf[item_cnt]=0; /* terminate the buffer, for sure */
! 345: fseek(fp,offset,SEEK_SET); /* reposition file pointer to the record */
! 346: if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */
! 347: /* printf("Error writing data to file\n"); */
! 348: errcode= (-1);
! 349: }
! 350: if (item_cnt != 0) {
! 351: if (!fwrite(big_buf,item_cnt,1,fp) ){/*write out the remainings*/
! 352: /* printf("Error writing data to file\n"); */
! 353: errcode= (-1);
! 354: }
! 355: }
! 356: new_size = ftell(fp);
! 357: if(new_size < orig_size ) {
! 358: fd = fileno(fp);
! 359: ftruncate(fd,new_size);
! 360: }
! 361: }
! 362: }
! 363: } else { /* end of file */
! 364: fseek(fp,0L,SEEK_END);
! 365: offset = ftell(fp); /* last byte, if last byte is cr, back up one */
! 366: fseek(fp,-1L,SEEK_END);
! 367: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
! 368: offset = offset +2; /* last char and cr */
! 369: done=1;
! 370: fseek(fp,offset,SEEK_SET);
! 371: if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */
! 372: /* printf("Error writing data to file\n"); */
! 373: errcode= (-1);
! 374: }
! 375: }
! 376: }
! 377: fflush(fp);
! 378: funlockstream(fp); /* <======= unlock the file */
! 379: fclose(fp);
! 380: capa_mfree(big_buf); /* free up the buffer */
! 381: return (errcode);
! 382: }
! 383:
! 384: /* for all elements in entry->answers that aren't ? it changes the
! 385: file to have the new values (except if student has a Y and for all
! 386: entries in entry->tries that don't have the value -1 it changes the
! 387: file to have the new value */
! 388:
! 389: int
! 390: capa_change_entry(entry, student_number, set)
! 391: T_entry *entry;
! 392: char *student_number;
! 393: int set;
! 394: {
! 395: FILE *fp;
! 396: int fd;
! 397: int errcode=0,offset=0;
! 398: int done, len, new_len, item_cnt,i,j;
! 399: long next_r, orig_size, new_size, big_buf_size;
! 400: char filename[FILE_NAME_LENGTH];
! 401: char *a_line, tmpline[TMP_LINE_LENGTH],
! 402: tmp_sn[MAX_STUDENT_NUMBER+1], fmtbuf[SMALL_LINE_BUFFER];
! 403: char *big_buf;
! 404:
! 405: sprintf(filename,"records/set%d.db",set);
! 406: if ((fp=fopen(filename,"r+"))==NULL) {
! 407: /* printf("Error capa_set_entry(): can't open %s\n",filename); */ return (-1);
! 408: }
! 409: /* entry->answers*3 == entry->tries, + fudge factor*/
! 410: a_line=capa_malloc(strlen(entry->tries)*5+MAX_STUDENT_NUMBER,1);
! 411: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
! 412: new_len = strlen(a_line);
! 413: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
! 414: flockstream(fp); /* <==== lock the setX.db file */
! 415: fseek(fp,0L,SEEK_END);
! 416: orig_size = ftell(fp);
! 417: big_buf_size = orig_size + new_len;
! 418: big_buf = capa_malloc(big_buf_size,1);
! 419: fseek(fp,0L,SEEK_SET); /* rewind to beginning of file */
! 420: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* skip weight line, including \n */
! 421: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* hand grading */
! 422: done = 0;
! 423: while(!done) {
! 424: done = !fgets(tmpline,TMP_LINE_LENGTH-1,fp); len = strlen(tmpline);
! 425: if( !done ) {
! 426: sscanf(tmpline,fmtbuf,tmp_sn);
! 427: if( !strncasecmp(tmp_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
! 428: next_r = ftell(fp); offset = next_r - len; done = 1;
! 429: item_cnt=fread(big_buf,1,big_buf_size,fp); /*read remaining lines into buffer*/
! 430: if(item_cnt >= 0 ) { /* no error reading remaining lines */
! 431: big_buf[item_cnt]=0; /* terminate the buffer, for sure */
! 432: fseek(fp,offset,SEEK_SET); /* reposition file pointer to the record */
! 433: for(i=0;i<entry->e_probs;i++) {
! 434: /*if entry has been updated, and student doesn't have a Y yet*/
! 435: if ((entry->answers[i]!='?') &&
! 436: (tmpline[MAX_STUDENT_NUMBER+1+i]!='Y'))
! 437: tmpline[MAX_STUDENT_NUMBER+1+i]=entry->answers[i];
! 438: j = atoi(&(entry->tries[i*3]));
! 439: if ( j > -1 ) {
! 440: tmpline[MAX_STUDENT_NUMBER+1+entry->e_probs+1+i*3]=entry->tries[i*3];
! 441: tmpline[MAX_STUDENT_NUMBER+1+entry->e_probs+1+i*3+1]=entry->tries[i*3+1];
! 442: }
! 443: }
! 444: if (!fwrite(tmpline,new_len,1,fp) ) { errcode= (-1); }
! 445: if (item_cnt != 0) {
! 446: if (!fwrite(big_buf,item_cnt,1,fp) ){/*write out the remainings*/
! 447: /* printf("Error writing data to file\n"); */
! 448: errcode= (-1);
! 449: }
! 450: }
! 451: new_size = ftell(fp);
! 452: if(new_size < orig_size ) {
! 453: fd = fileno(fp);
! 454: ftruncate(fd,new_size);
! 455: }
! 456: }
! 457: }
! 458: } else { /* end of file */
! 459: fseek(fp,0L,SEEK_END);
! 460: offset = ftell(fp); /* last byte, if last byte is cr, back up one */
! 461: fseek(fp,-1L,SEEK_END);
! 462: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
! 463: offset = offset +2; /* last char and cr */
! 464: done=1;
! 465: fseek(fp,offset,SEEK_SET);
! 466: if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */
! 467: /* printf("Error writing data to file\n"); */
! 468: errcode= (-1);
! 469: }
! 470: }
! 471: }
! 472: fflush(fp);
! 473: funlockstream(fp); /* <======= unlock the file */
! 474: fclose(fp);
! 475: capa_mfree(big_buf); /* free up the buffer */
! 476: return (errcode);
! 477: }
! 478:
! 479: /* -------------------------------------------------- */
! 480: /* append a entry record to the very end of the file */
! 481: long
! 482: capa_append_entry(entry, student_number, set)
! 483: T_entry *entry;
! 484: char *student_number;
! 485: int set;
! 486: {
! 487: FILE *fp;
! 488: int len;
! 489: char filename[FILE_NAME_LENGTH];
! 490: char a_line[TMP_LINE_LENGTH];
! 491: long offset;
! 492:
! 493: sprintf(filename,"records/set%d.db",set);
! 494: if ((fp=fopen(filename,"r+"))==NULL) {
! 495: /* printf("Error capa_set_entry(): can't open %s\n",filename); */
! 496: return (-1);
! 497: }
! 498: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
! 499: len = strlen(a_line);
! 500:
! 501: flockstream(fp); /* <==== lock the setX.db file */
! 502: fseek(fp,0L,SEEK_END);
! 503: offset = ftell(fp);
! 504: fseek(fp,-1L,SEEK_END);
! 505: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
! 506: offset = offset +2;
! 507: fseek(fp,offset,SEEK_SET);
! 508: if (!fwrite(a_line,len,1,fp) ) {
! 509: /* printf("Error writing data to file\n"); */
! 510: return (-1);
! 511: }
! 512: fflush(fp);
! 513: funlockstream(fp);
! 514: fclose(fp);
! 515: return (offset);
! 516: }
! 517:
! 518: /*----------------------------------------------------------*/
! 519:
! 520: long /* RETURNS: byte offset to start of record, 0 if error,
! 521: -offset if not found & newly created */
! 522: capa_get_entry(entry, student_number, set)
! 523: T_entry *entry;
! 524: char *student_number;
! 525: int set;
! 526: {
! 527: char filename[FILE_NAME_LENGTH];
! 528: FILE *fp;
! 529: int len, nq;
! 530: char *ans_p, *tries_p, oneline[TMP_LINE_LENGTH],fmtbuf[SMALL_LINE_BUFFER];
! 531: long offset = 0, next_r;
! 532: int ii, done, found = 0;
! 533: char a_sn[MAX_STUDENT_NUMBER+1];
! 534:
! 535: sprintf(filename,"records/set%d.db",set);
! 536: if ((fp=fopen(filename,"r"))==NULL) {
! 537: /*printf("Error capa_get_entry(): can't open %s\n",filename);*/
! 538: return (0);
! 539: }
! 540: sprintf(entry->student_number,"%s",student_number);
! 541: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
! 542: flockstream(fp);
! 543: fgets(oneline,TMP_LINE_LENGTH-1,fp); len = strlen(oneline); sscanf(oneline,"%d",&nq);
! 544: fgets(oneline,TMP_LINE_LENGTH-1,fp); /* skip weight line, including \n */
! 545: fgets(oneline,TMP_LINE_LENGTH-1,fp); /* hand grading */
! 546: done = 0;
! 547: while(!done) {
! 548: done = !fgets(oneline,TMP_LINE_LENGTH-1,fp); len = strlen(oneline);
! 549: if( !done ) {
! 550: sscanf(oneline,fmtbuf,a_sn);
! 551: if( !strncasecmp(a_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
! 552: next_r = ftell(fp); offset = next_r - len; done = 1; found = 1;
! 553: }
! 554: } else { /* end of file */
! 555: fseek(fp,0L,SEEK_END);
! 556: offset = ftell(fp); /* last byte, if last bye is cr, back up one */
! 557: fseek(fp,-1L,SEEK_END);
! 558: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
! 559: offset = offset +2; /* last char and cr */
! 560: found = 0; done=1;
! 561: }
! 562: }
! 563: funlockstream(fp); fclose(fp);
! 564: if(!found) {
! 565: ans_p = capa_malloc(nq+1,1);
! 566: tries_p = capa_malloc(3*nq+2,1); /* space and \0 */
! 567: for(ii=0;ii<nq;ii++) { /* Initialize answer string and tries string */
! 568: ans_p[ii] = '-'; tries_p[3*ii] = ' '; tries_p[3*ii + 1] = '0';
! 569: if(ii < nq-1) tries_p[3*ii + 2] = ',';
! 570: }
! 571: entry->answers = ans_p;
! 572: entry->tries = tries_p;
! 573: entry->e_probs = nq;
! 574: offset = capa_append_entry(entry,student_number,set);
! 575: } else { /* grows records shorter than nq to nq in length*/
! 576: char *comma;
! 577: int length;
! 578: comma=index(oneline,',');
! 579: length=((int)(comma-oneline))-(MAX_STUDENT_NUMBER+1);
! 580: if (length < nq) {
! 581: ans_p = capa_malloc(nq+1,1);
! 582: tries_p = capa_malloc(3*nq+2,1); /* space and \0 */
! 583: } else {
! 584: ans_p = capa_malloc(length+1,1);
! 585: tries_p = capa_malloc(3*length+2,1); /* space and \0 */
! 586: }
! 587: sprintf(fmtbuf, "%%%dc",length);
! 588: sscanf(oneline + MAX_STUDENT_NUMBER+1,fmtbuf,ans_p);
! 589: sprintf(fmtbuf, "%%%dc",(3*length-1));
! 590: sscanf(oneline + MAX_STUDENT_NUMBER+1+length+1,fmtbuf,tries_p);
! 591: entry->answers = ans_p;
! 592: entry->tries = tries_p;
! 593: entry->e_probs = nq;
! 594: if (length < nq) {
! 595: for(ii=length;ii<nq;ii++) {
! 596: ans_p[ii] = '-'; tries_p[3*ii] = ' '; tries_p[3*ii + 1] = '0';
! 597: if(ii < nq-1) tries_p[3*ii + 2] = ',';
! 598: }
! 599: ans_p[nq]='\0';tries_p[3*(nq)+2]='\0';tries_p[3*length-1]=',';
! 600: }
! 601: }
! 602: return (offset);
! 603: }
! 604: /*----------------------------------------------------------*/
! 605: /* Constants defining the column number for each fields */
! 606: /* in classl file */
! 607: /*----------------------------------------------------------*/
! 608: #define SECTION_BEGIN_COLUMN 10
! 609: #define SN_BEGIN_COLUMN 14
! 610: #define NAME_BEGIN_COLUMN 24
! 611: #define EMAIL_BEGIN_COLUMN 60
! 612: #define CAPAID_BEGIN_COLUMN 100
! 613: /*----------------------------------------------------------*/
! 614: /* Retrieve a linked list of students with specified */
! 615: /* section in classl file */
! 616: /* If the input section number is 0, students in the whole */
! 617: /* classl will be retrieved. */
! 618: /* The resulting linked list is ordered according to the */
! 619: /* order in classl */
! 620: /* Remember to use free_students() to free up the linked */
! 621: /* list once done with it. */
! 622: /*----------------------------------------------------------*/
! 623: /* INPUT: section section number */
! 624: /* 0 means to load the whole class */
! 625: /* OUTPUT: student_pp */
! 626: /* pointer to pointer of structure T_student */
! 627: /* RETURN: number of students in specified section */
! 628: /*----------------------------------------------------------*/
! 629: int
! 630: capa_get_section(student_pp, section)
! 631: T_student **student_pp;
! 632: int section;
! 633: {
! 634: FILE *fp;
! 635: char line[SMALL_LINE_BUFFER],fmtbuf[SMALL_LINE_BUFFER], *cp;
! 636: int i, line_len;
! 637: int tmp_sec, student_cnt, tmp_capaid;
! 638: T_student *s1_p, *s2_p, *s3_p;
! 639:
! 640: if ((fp=fopen("classl","r"))==NULL) {
! 641: /*printf("Error: Can't open classlist file\n");*/
! 642: return (-1);
! 643: }
! 644: student_cnt = 0; s1_p = s2_p = s3_p = (T_student *)NULL;
! 645: while (fgets(line,SMALL_LINE_BUFFER-1,fp)) {
! 646: line_len = strlen(line);
! 647: if(line_len > 25 ) { /* contains valid information, instead of only cr */
! 648: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &tmp_sec);
! 649: if (!section || tmp_sec == section) {
! 650: s3_p = (T_student *)capa_malloc(sizeof(T_student),1);
! 651: s3_p->s_sec = tmp_sec;
! 652: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
! 653: sscanf(line+SN_BEGIN_COLUMN,fmtbuf,s3_p->s_sn);
! 654: cp = (char *)&line[NAME_BEGIN_COLUMN];
! 655: for(i=0;i<MAX_NAME_CHAR;i++) s3_p->s_nm[i]=' ';
! 656: i=0;
! 657: while( (i < MAX_NAME_CHAR) &&
! 658: ( isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
! 659: cp[i] == ' ' || cp[i] == '\t'|| cp[i] == '-' ) ) {
! 660: s3_p->s_nm[i]=cp[i]; i++;
! 661: }
! 662: s3_p->s_nm[MAX_NAME_CHAR]='\0';
! 663: s3_p->s_email[0]=0;
! 664: if( line_len > EMAIL_BEGIN_COLUMN ) { /* contains email */
! 665: cp = (char *)&line[EMAIL_BEGIN_COLUMN];
! 666: for(i=0;i<MAX_EMAIL_CHAR;i++) s3_p->s_email[i]=' ';
! 667: i=0;
! 668: while( (i < MAX_EMAIL_CHAR) &&
! 669: ( isalnum(cp[i]) || cp[i] == '@' || cp[i] == '.' ) ) {
! 670: s3_p->s_email[i]=cp[i]; i++;
! 671: }
! 672: s3_p->s_email[i]='\0'; /* terminate the email string with the string length */
! 673: if( line_len > CAPAID_BEGIN_COLUMN ) { /* contains capa id */
! 674: sscanf(line+CAPAID_BEGIN_COLUMN,"%d", &tmp_capaid);
! 675: if(tmp_capaid > 0 ) {
! 676: s3_p->s_capaid = tmp_capaid;
! 677: }
! 678: }
! 679: }
! 680: if( student_cnt == 0 ) {
! 681: s1_p = s3_p;
! 682: s3_p->s_prev = s3_p; s3_p->s_next = (T_student *)NULL;
! 683: s2_p = s3_p;
! 684: } else {
! 685: s3_p->s_prev = s2_p; s3_p->s_next = (T_student *)NULL;
! 686: s2_p->s_next = s3_p;
! 687: s2_p = s3_p;
! 688: }
! 689: student_cnt++;
! 690: }
! 691: }
! 692: }
! 693: fclose(fp);
! 694: *student_pp = s1_p;
! 695: return (student_cnt);
! 696: }
! 697: /*----------------------------------------------------------*/
! 698: /*----------------------------------------------------------*/
! 699: /* Retrieve a linked list of students with specified */
! 700: /* section in classl file */
! 701: /* If the input section number is 0, students in the whole */
! 702: /* classl will be retrieved. */
! 703: /* The resulting linked list is ordered according to */
! 704: /* student name */
! 705: /* Remember to use free_students() to free up the linked */
! 706: /* list once done with it. */
! 707: /*----------------------------------------------------------*/
! 708: /* INPUT: section section number */
! 709: /* 0 means to load the whole class */
! 710: /* OUTPUT: student_pp */
! 711: /* pointer to pointer of structure T_student */
! 712: /* RETURN: number of students in specified section */
! 713: /*----------------------------------------------------------*/
! 714:
! 715: int
! 716: capa_sorted_section(student_pp, section)
! 717: T_student **student_pp;
! 718: int section;
! 719: {
! 720: int student_cnt;
! 721: T_student *student_p, *c_sp;
! 722:
! 723: student_cnt = capa_get_section(&student_p,section);
! 724: if( student_cnt > 1 ) {
! 725: for(c_sp=student_p;c_sp;c_sp=c_sp->s_next){
! 726: strcpy(c_sp->s_key,c_sp->s_nm);
! 727: }
! 728: msort_main(&student_p);
! 729: }
! 730: *student_pp = student_p;
! 731: return (student_cnt);
! 732: }
! 733:
! 734: /*----------------------------------------------------------*/
! 735: /* INPUT: address of a pointer to T_student structure */
! 736: /* OUTPUT: address of a pointer to T_student structure */
! 737: /* */
! 738: /* RETURN: none */
! 739: /*----------------------------------------------------------*/
! 740: void
! 741: msort_main(head_pp) T_student **head_pp;
! 742: {
! 743: T_student *right_p, *out_sp;
! 744:
! 745: if( (*head_pp != NULL) && ((*head_pp)->s_next != NULL) ) {
! 746: msort_split( *head_pp, &right_p);
! 747: msort_main(head_pp); msort_main(&right_p);
! 748: msort_merge(*head_pp, right_p, &out_sp);
! 749: *head_pp = out_sp;
! 750: }
! 751: }
! 752: /*----------------------------------------------------------*/
! 753: /* INPUT: a_sp pointer to T_student structur */
! 754: /* OUTPUT: a_sp */
! 755: /* b_pp address of a pointer to T_student structure */
! 756: /* */
! 757: /* RETURN: none */
! 758: /*----------------------------------------------------------*/
! 759: void
! 760: msort_split(a_sp, b_pp) T_student *a_sp; T_student **b_pp;
! 761: {
! 762: T_student *c_sp;
! 763:
! 764: *b_pp = a_sp;
! 765: c_sp = a_sp->s_next;
! 766: c_sp = c_sp->s_next;
! 767: while( c_sp != NULL ) {
! 768: c_sp = c_sp->s_next;
! 769: *b_pp = (*b_pp)->s_next;
! 770: if( c_sp != NULL ) c_sp = c_sp->s_next;
! 771: }
! 772: c_sp = (*b_pp)->s_next;
! 773: (*b_pp)->s_next = NULL;
! 774: *b_pp = c_sp;
! 775: }
! 776: /*----------------------------------------------------------*/
! 777: /* INPUT: a_sp pointer to T_student structur */
! 778: /* b_sp pointer to T_student structur */
! 779: /* OUTPUT: c_pp address of a pointer to T_student structure */
! 780: /* */
! 781: /* RETURN: none */
! 782: /*----------------------------------------------------------*/
! 783: void
! 784: msort_merge(a_sp, b_sp, c_pp) T_student *a_sp, *b_sp, **c_pp;
! 785: {
! 786: T_student *d_sp;
! 787:
! 788: if( a_sp == NULL || b_sp == NULL ) {
! 789:
! 790: } else {
! 791: if( strcmp(a_sp->s_key, b_sp->s_key) <= 0 ) {
! 792: *c_pp = a_sp;
! 793: a_sp = a_sp->s_next;
! 794: } else {
! 795: *c_pp = b_sp;
! 796: b_sp = b_sp->s_next;
! 797: }
! 798: d_sp = *c_pp;
! 799: while( (a_sp != NULL) && (b_sp != NULL) ) {
! 800: if( strcmp(a_sp->s_key, b_sp->s_key) <= 0) {
! 801: d_sp->s_next = a_sp;
! 802: d_sp = a_sp;
! 803: a_sp = a_sp->s_next;
! 804: } else {
! 805: d_sp->s_next = b_sp;
! 806: d_sp = b_sp;
! 807: b_sp = b_sp->s_next;
! 808: }
! 809: }
! 810: if( a_sp == NULL ) {
! 811: d_sp->s_next = b_sp;
! 812: } else {
! 813: d_sp->s_next = a_sp;
! 814: }
! 815: }
! 816: }
! 817:
! 818: /*----------------------------------------------------------*/
! 819: /* INPUT: head_p pointer to T_student structure */
! 820: /* OUTPUT: head_p pointed to sorted linked list */
! 821: /* */
! 822: /* RETURN: none */
! 823: /*----------------------------------------------------------*/
! 824: void
! 825: insert_sort(head_p) T_student *head_p;
! 826: {
! 827: T_student *tail_p, *i_p, *p_p, *r_p;
! 828:
! 829: if( head_p != NULL ) {
! 830: tail_p = head_p;
! 831: while( tail_p->s_next != NULL ) {
! 832: i_p = tail_p->s_next;
! 833: if( strcmp( i_p->s_key, head_p->s_key) < 0 ) {
! 834: tail_p->s_next = i_p->s_next;
! 835: i_p->s_next = head_p;
! 836: head_p = i_p;
! 837: } else {
! 838: r_p = head_p;
! 839: p_p = r_p->s_next;
! 840: while( strcmp(i_p->s_key, p_p->s_key) > 0 ) {
! 841: r_p = p_p;
! 842: p_p = r_p->s_next;
! 843: }
! 844: if( i_p == p_p ) {
! 845: tail_p = i_p;
! 846: } else {
! 847: tail_p->s_next = i_p->s_next;
! 848: i_p->s_next = p_p;
! 849: r_p->s_next = i_p;
! 850: }
! 851: }
! 852: }
! 853: }
! 854: }
! 855: /*----------------------------------------------------------*/
! 856: /* The purpose of this routine is to free up all spaces */
! 857: /* in the linked list */
! 858: /*----------------------------------------------------------*/
! 859: /* INPUT: student_p pointer to T_student structure */
! 860: /* OUTPUT: none */
! 861: /* */
! 862: /* RETURN: none */
! 863: /*----------------------------------------------------------*/
! 864:
! 865: void
! 866: free_students(student_p) T_student *student_p;
! 867: {
! 868: T_student *s_p,*next_p;
! 869:
! 870: for (s_p=student_p; s_p; s_p=next_p) {
! 871: next_p = (s_p->s_next);
! 872: capa_mfree((char *)s_p);
! 873: }
! 874: }
! 875:
! 876: /*----------------------------------------------------------*/
! 877: /* The purpose of this routine is to free up all spaces */
! 878: /* in the linked list */
! 879: /*----------------------------------------------------------*/
! 880: /* INPUT: student_p pointer to T_student structur */
! 881: /* OUTPUT: none */
! 882: /* */
! 883: /* RETURN: -2 file error */
! 884: /* -1 never login */
! 885: /* >= 0 score for that set */
! 886: /*----------------------------------------------------------*/
! 887: int
! 888: capa_get_score(student_number,set,valid_scores,answers_pp)
! 889: char *student_number;int set;int *valid_scores;char **answers_pp;
! 890: {
! 891: T_entry a_record;
! 892: T_header a_header;
! 893: long offset;
! 894: int set_scores, set_valids=0, probs_cnt;
! 895: int ii=0, never_login=1;
! 896:
! 897: if( (offset = capa_get_entry(&a_record,student_number,set) ) == 0 ) {
! 898: return (-2);
! 899: }
! 900: probs_cnt = a_record.e_probs;
! 901: if( capa_get_header(&a_header,set) < 0 ) { return (-2); }
! 902: if( offset < 0 ) {
! 903: for(set_valids=0,ii=0;ii<probs_cnt;ii++) {
! 904: set_valids += (a_header.weight[ii] - '0');
! 905: }
! 906: set_scores = -1;
! 907: *answers_pp = a_record.answers;
! 908: capa_mfree(a_record.tries); a_record.tries = NULL;
! 909: } else {
! 910: for(set_scores=0,ii=0, never_login=1;ii<probs_cnt;ii++) {
! 911: switch(a_record.answers[ii]) {
! 912: case 'Y': case 'y': never_login = 0;
! 913: set_scores += (a_header.weight[ii] - '0');
! 914: set_valids += (a_header.weight[ii] - '0'); break;
! 915: case '-': case 'N': case 'n':
! 916: set_valids += (a_header.weight[ii] - '0'); break;
! 917: case 'E': case 'e': break;
! 918: default : if( a_record.answers[ii] >= '0' &&
! 919: a_record.answers[ii] <= '9' ) {
! 920: set_scores += (a_record.answers[ii] - '0');
! 921: set_valids += (a_header.weight[ii] - '0');
! 922: never_login = 0;
! 923: } break;
! 924: }
! 925: }
! 926: *answers_pp = a_record.answers;
! 927: capa_mfree(a_record.tries); a_record.tries = NULL;
! 928: }
! 929: capa_mfree(a_header.weight);
! 930: capa_mfree(a_header.partial_credit);
! 931: *valid_scores = set_valids;
! 932: if(never_login) set_scores = -1;
! 933: return (set_scores);
! 934: }
! 935: /*----------------------------------------------------------*/
! 936: /* Reads the classl file and returns the number of students */
! 937: /* for each section in cnt_arry[] */
! 938: /* In cnt_arry[0] is the maximum section number that */
! 939: /* has at least one student */
! 940: /*----------------------------------------------------------*/
! 941: /* INPUT: cnt_arry[] integer array */
! 942: /* OUTPUT: cnt_arry[] */
! 943: /* */
! 944: /* */
! 945: /* RETURN: -1 file error */
! 946: /*----------------------------------------------------------*/
! 947: int
! 948: capa_get_section_count(cnt_arry) int cnt_arry[];
! 949: {
! 950: FILE *fp;
! 951: char filename[FILE_NAME_LENGTH];
! 952: char line[TMP_LINE_LENGTH];
! 953: int sec_num, cnt, i, max;
! 954:
! 955: sprintf(filename,"classl");
! 956: if ((fp=fopen(filename,"r"))==NULL) {
! 957: /*printf("Error: can't open %s\n",filename);*/
! 958: return (-1);
! 959: }
! 960: for(i=0;i<MAX_SECTION_COUNT;i++) cnt_arry[i]=0;
! 961: max = 0;
! 962: while ( fgets(line,TMP_LINE_LENGTH-1,fp) && (strlen(line) != 0) ) {
! 963: sec_num=0;
! 964: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &sec_num);
! 965: if( sec_num != 0 ) {
! 966: max = MAX(sec_num,max);
! 967: cnt_arry[sec_num]++;
! 968: }
! 969: }
! 970: fclose(fp);
! 971: cnt = 0;
! 972: for(i=1; i <= max; i++) {
! 973: if(cnt_arry[i]) cnt++;
! 974: }
! 975: cnt_arry[0] = max;
! 976: return (cnt);
! 977: }
! 978: /*----------------------------------------------------------*/
! 979: /* lookup student information from classl file by */
! 980: /* student number */
! 981: /*----------------------------------------------------------*/
! 982: /* INPUT: student_number char array of student number */
! 983: /* OUTPUT: student_p pointer to a T_student structure */
! 984: /* that contains the student name, */
! 985: /* student number, section number */
! 986: /* of the student inquired */
! 987: /* */
! 988: /* RETURN: -1 file error */
! 989: /* 0 no such student */
! 990: /* >0 success (line number in classl of student)*/
! 991: /*----------------------------------------------------------*/
! 992: int
! 993: capa_get_student(student_number, student_p)
! 994: char *student_number;
! 995: T_student *student_p;
! 996: {
! 997: FILE *fp;
! 998: char line[SMALL_LINE_BUFFER],fmtbuf[SMALL_LINE_BUFFER],
! 999: sNumber[MAX_STUDENT_NUMBER+1],
! 1000: aNumber[MAX_STUDENT_NUMBER+1];
! 1001: int i,found,line_len,tmp_capaid,linenum=0;
! 1002: char *cp;
! 1003:
! 1004: strncpy(sNumber, student_number,MAX_STUDENT_NUMBER+1);
! 1005: if ((fp=fopen("classl","r"))==NULL) {
! 1006: /*printf("Error: Can't open classlist file\n");*/
! 1007: return (-1);
! 1008: }
! 1009: found = 0;
! 1010: while (!found && fgets(line,SMALL_LINE_BUFFER-1,fp)) {
! 1011: linenum++;
! 1012: line_len = strlen(line);
! 1013: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
! 1014: sscanf(line+SN_BEGIN_COLUMN,fmtbuf,aNumber);
! 1015: if(!strncasecmp(sNumber,aNumber, MAX_STUDENT_NUMBER)) {
! 1016: found = 1;
! 1017: i=0;
! 1018: strncpy(student_p->s_sn, student_number,MAX_STUDENT_NUMBER+1);
! 1019: cp = (char *)&line[NAME_BEGIN_COLUMN];
! 1020: while( (i< MAX_NAME_CHAR) &&
! 1021: (isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
! 1022: cp[i] == ' ' || cp[i] == '\t'|| cp[i] == '-' || cp[i] == '_' || cp[i] == '~' ) ) {
! 1023: student_p->s_nm[i]=cp[i]; i++;
! 1024: }
! 1025: student_p->s_nm[i]='\0';
! 1026: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &(student_p->s_sec));
! 1027: student_p->s_email[0]=0;
! 1028: if( line_len > EMAIL_BEGIN_COLUMN ) { /* contains email */
! 1029: cp = (char *)&line[EMAIL_BEGIN_COLUMN];
! 1030: for(i=0;i<MAX_EMAIL_CHAR;i++) student_p->s_email[i]=' ';
! 1031: i=0;
! 1032: while( (i < MAX_EMAIL_CHAR) &&
! 1033: ( isalnum(cp[i]) || cp[i] == '@' || cp[i] == '.' || cp[i] == '!' || cp[i] == '=' ||
! 1034: cp[i] == '_' || cp[i] == '-' || cp[i] == '+' || cp[i] == '^' || cp[i] == '|' ) ) {
! 1035: student_p->s_email[i]=cp[i]; i++;
! 1036: }
! 1037: student_p->s_email[i]='\0'; /* terminate the email string with the string length */
! 1038: if( line_len > CAPAID_BEGIN_COLUMN ) { /* contains capa id */
! 1039: sscanf(line+CAPAID_BEGIN_COLUMN,"%d", &tmp_capaid);
! 1040: if(tmp_capaid > 0 ) {
! 1041: student_p->s_capaid = tmp_capaid;
! 1042: }
! 1043: }
! 1044: }
! 1045: }
! 1046: }
! 1047: fclose(fp);
! 1048: if (found > 0) found=linenum;
! 1049: return (found);
! 1050: }
! 1051: /*----------------------------------------------------------*/
! 1052: /* lookup student information from classl file by */
! 1053: /* student name */
! 1054: /*----------------------------------------------------------*/
! 1055: /* INPUT: student_name char array of student name */
! 1056: /* OUTPUT: student_p pointer to a T_student structure */
! 1057: /* that contains the student name, */
! 1058: /* student number, section number */
! 1059: /* of the student inquired */
! 1060: /* */
! 1061: /* RETURN: -1 file error */
! 1062: /* 0 no such student */
! 1063: /* 1 success */
! 1064: /*----------------------------------------------------------*/
! 1065: int
! 1066: capa_student_byname(student_name, student_p)
! 1067: char *student_name;
! 1068: T_student *student_p;
! 1069: {
! 1070: FILE *fp;
! 1071: char line[SMALL_LINE_BUFFER],fmtbuf[SMALL_LINE_BUFFER],
! 1072: sName[MAX_NAME_CHAR+1],
! 1073: aName[MAX_NAME_CHAR+1];
! 1074: int i,found, len, line_len,tmp_capaid;
! 1075: char *cp;
! 1076:
! 1077: len = strlen(student_name);
! 1078: strncpy(sName, student_name,MAX_NAME_CHAR+1);
! 1079: if ((fp=fopen("classl","r"))==NULL) {
! 1080: /*printf("Error: Can't open classlist file\n");*/
! 1081: return (-1);
! 1082: }
! 1083: found = 0;
! 1084: while (fgets(line,SMALL_LINE_BUFFER-1,fp)) {
! 1085: i=0;
! 1086: cp = (char *)&line[NAME_BEGIN_COLUMN];
! 1087: while( (i < MAX_NAME_CHAR) &&
! 1088: (isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
! 1089: cp[i] == ' ' || cp[i] == '\t' || cp[i] == '-' || cp[i] == '_' || cp[i] == '~') ) {
! 1090: aName[i]=cp[i]; i++;
! 1091: }
! 1092: aName[i]='\0';
! 1093: if(!strncasecmp(sName,aName,len)) {
! 1094: found = 1;
! 1095: strcpy(student_p->s_nm,aName);
! 1096: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &(student_p->s_sec));
! 1097: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
! 1098: sscanf(line+SN_BEGIN_COLUMN,fmtbuf,student_p->s_sn);
! 1099: student_p->s_email[0]=0;
! 1100: line_len=strlen(line);
! 1101: if( line_len > EMAIL_BEGIN_COLUMN ) { /* contains email */
! 1102: cp = (char *)&line[EMAIL_BEGIN_COLUMN];
! 1103: for(i=0;i<MAX_EMAIL_CHAR;i++) student_p->s_email[i]=' ';
! 1104: i=0;
! 1105: while( (i < MAX_EMAIL_CHAR) &&
! 1106: ( isalnum(cp[i]) || cp[i] == '@' || cp[i] == '.' || cp[i] == '!' || cp[i] == '=' ||
! 1107: cp[i] == '_' || cp[i] == '-' || cp[i] == '+' || cp[i] == '^' || cp[i] == '|' ) ) {
! 1108: student_p->s_email[i]=cp[i]; i++;
! 1109: }
! 1110: student_p->s_email[i]='\0'; /* terminate the email string with the string length */
! 1111: if( line_len > CAPAID_BEGIN_COLUMN ) { /* contains capa id */
! 1112: sscanf(line+CAPAID_BEGIN_COLUMN,"%d", &tmp_capaid);
! 1113: if(tmp_capaid > 0 ) {
! 1114: student_p->s_capaid = tmp_capaid;
! 1115: }
! 1116: }
! 1117: }
! 1118: }
! 1119: }
! 1120: fclose(fp);
! 1121: return (found);
! 1122: }
! 1123: /*----------------------------------------------------------*/
! 1124: /* Randomly selected a student from classl file specified */
! 1125: /* by section */
! 1126: /*----------------------------------------------------------*/
! 1127: /* INPUT: section section number */
! 1128: /* OUTPUT: student_p pointer to a T_student structure */
! 1129: /* that contains the student name, */
! 1130: /* student number, section number */
! 1131: /* of the student inquired */
! 1132: /* */
! 1133: /* RETURN: -1 file error */
! 1134: /* 0 no such student */
! 1135: /* 1 success */
! 1136: /*----------------------------------------------------------*/
! 1137: int
! 1138: capa_pick_student(section, student_p)
! 1139: int section;
! 1140: T_student *student_p;
! 1141: {
! 1142: T_student *s1_p, *s2_p;
! 1143: int student_cnt, idx, pick=-1;
! 1144:
! 1145: student_cnt = capa_get_section(&s1_p,section);
! 1146: if(student_cnt > 0 ) {
! 1147: srand(time(NULL));
! 1148: pick = rand() % student_cnt;
! 1149: for(s2_p = s1_p, idx=0; s2_p && idx < pick; idx++) {
! 1150: s2_p = s2_p->s_next;
! 1151: }
! 1152: strcpy(student_p->s_sn,s2_p->s_sn);
! 1153: strcpy(student_p->s_nm,s2_p->s_nm);
! 1154: strcpy(student_p->s_email,s2_p->s_email);
! 1155: student_p->s_capaid=s2_p->s_capaid;
! 1156: student_p->s_sec = s2_p->s_sec;
! 1157: free_students(s1_p);
! 1158: }
! 1159: return (pick);
! 1160: }
! 1161: /* -------------------------------------------------- */
! 1162: /* add a student to the class file */
! 1163: /* check duplicated student id */
! 1164: /* student name? */
! 1165: /* Returns: 0 success */
! 1166: /* 1 there is an duplicate entry */
! 1167: /* -------------------------------------------------- */
! 1168: int
! 1169: capa_add_student(student_p)
! 1170: T_student *student_p;
! 1171: {
! 1172: FILE *fp;
! 1173: char line[SMALL_LINE_BUFFER], fmtbuf1[SMALL_LINE_BUFFER],
! 1174: tmp_nm[MAX_STUDENT_NUMBER+1],
! 1175: tmp_nu[MAX_NAME_CHAR+1];
! 1176: int i,found, len;
! 1177: char *class, *cp;
! 1178: char cid[4],cn[4];
! 1179: #if defined(NeXT)
! 1180: char cwd[FILE_NAME_LENGTH];
! 1181: #endif
! 1182:
! 1183: #if defined(NeXT)
! 1184: class = getwd(cwd);
! 1185: if( class == NULL ) { class = cwd; }
! 1186: #else
! 1187: class = getcwd(NULL,255);
! 1188: #endif
! 1189:
! 1190: if( class == NULL ) { printf("capa_add_student(): Current working directory unknown!\n"); }
! 1191: len=strlen(class); cp=class; cp=cp+(len-8);
! 1192: for(i=0;i<3;i++) {
! 1193: cid[i] = cp[i+3];
! 1194: cn[i] = cp[i];
! 1195: }
! 1196: cid[3]=cn[3]=0;
! 1197: if ((fp=fopen("classl","r+"))==NULL) {
! 1198: /*printf("Error: Can't open classlist file\n");*/
! 1199: return (-1);
! 1200: }
! 1201: found = 0;
! 1202: sprintf(fmtbuf1, "%%%dc",MAX_STUDENT_NUMBER);
! 1203: while (fgets(line,SMALL_LINE_BUFFER-1,fp)) {
! 1204: sscanf(line+SN_BEGIN_COLUMN,fmtbuf1,tmp_nu);
! 1205: tmp_nu[MAX_STUDENT_NUMBER]='\0';
! 1206: if(!strncasecmp(student_p->s_sn,tmp_nu, MAX_STUDENT_NUMBER)) {
! 1207: found = 1; break;
! 1208: }
! 1209: i=0; cp = (char *)&line[NAME_BEGIN_COLUMN];
! 1210: while( (i < MAX_NAME_CHAR) &&
! 1211: (isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
! 1212: cp[i] == ' ' || cp[i] == '\t'|| cp[i] == '-' || cp[i] == '_' || cp[i] == '~') ) {
! 1213: tmp_nm[i]=cp[i]; i++;
! 1214: }
! 1215: tmp_nm[i]='\0';
! 1216: len=strlen(tmp_nm);
! 1217: if(!strncasecmp(student_p->s_nm,tmp_nm,len)) {
! 1218: found = 1; break;
! 1219: }
! 1220: }
! 1221: if(!found) {
! 1222: sprintf(line,"%s %s %03d %s %s\n",
! 1223: cn,cid,student_p->s_sec,student_p->s_sn,student_p->s_nm);
! 1224: len = strlen(line);
! 1225: fseek(fp,0L,SEEK_END);
! 1226: if (!fwrite(line,len,1,fp) ) {
! 1227: /*printf("Error writing data to file\n");*/
! 1228: found = -1;
! 1229: }
! 1230: fflush(fp);
! 1231: }
! 1232: fclose(fp);
! 1233: free(class);
! 1234: return (found);
! 1235: }
! 1236: /*----------------------------------------------------------*/
! 1237: /* INPUT: student_number char array of student number */
! 1238: /* set the X in logX.db */
! 1239: /* OUTPUT: none */
! 1240: /* */
! 1241: /* RETURN: -1 file error */
! 1242: /* 0 no login */
! 1243: /* >0 number of logins in that logX.db file */
! 1244: /*----------------------------------------------------------*/
! 1245: int
! 1246: capa_get_login_count(student_number,set)
! 1247: char *student_number;
! 1248: int set;
! 1249: {
! 1250: char filename[FILE_NAME_LENGTH],
! 1251: sNumber[MAX_STUDENT_NUMBER+1],
! 1252: aNumber[MAX_STUDENT_NUMBER+1];
! 1253: FILE *fp;
! 1254: char line[MAX_BUFFER_SIZE],fmtbuf[MAX_BUFFER_SIZE];
! 1255: int num;
! 1256:
! 1257: strncpy(sNumber, student_number,MAX_STUDENT_NUMBER+1);
! 1258: sprintf(filename,"records/log%d.db",set);
! 1259: if( !capa_access(filename, F_OK) ) {
! 1260: if ((fp=fopen(filename,"r"))==NULL) {
! 1261: /*printf("Error: can't open %s\n",filename);*/
! 1262: return (-1);
! 1263: }
! 1264: } else {
! 1265: return (-1);
! 1266: }
! 1267: num = 0;
! 1268: while (fgets(line,MAX_BUFFER_SIZE-1,fp)) {
! 1269: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
! 1270: sscanf(line,fmtbuf,aNumber);
! 1271: if(!strncasecmp(sNumber,aNumber, MAX_STUDENT_NUMBER)) num++;
! 1272: }
! 1273: fclose(fp);
! 1274: return (num);
! 1275: }
! 1276: /*----------------------------------------------------------*/
! 1277: /* INPUT: set the X in logX.db */
! 1278: /* OUTPUT: none */
! 1279: /* */
! 1280: /* RETURN: -1 file error */
! 1281: /* 0 no login */
! 1282: /* >0 number of logins in that logX.db file */
! 1283: /*----------------------------------------------------------*/
! 1284: #define ANSWER_BEGIN_COLUMN 35
! 1285: int
! 1286: capa_get_login_db(login_item,num_probs,set)
! 1287: T_entry login_item[];
! 1288: int *num_probs;
! 1289: int set;
! 1290: {
! 1291: FILE *fp;
! 1292: char filename[FILE_NAME_LENGTH];
! 1293: char line[MAX_BUFFER_SIZE],fmtbuf[SMALL_LINE_BUFFER];
! 1294: T_header header;
! 1295: int num_q, count, len;
! 1296:
! 1297: if(capa_get_header(&header,set)) return (0);
! 1298: sscanf(header.num_questions,"%d",&num_q);
! 1299: *num_probs = num_q;
! 1300: capa_mfree(header.weight);
! 1301: capa_mfree(header.partial_credit);
! 1302:
! 1303: sprintf(filename,"records/log%d.db",set);
! 1304: if((fp=fopen(filename,"r"))==NULL) {
! 1305: /*printf("Error: can't open %s\n",filename);*/
! 1306: return (-1);
! 1307: }
! 1308: count=0;
! 1309: while ( fgets(line,MAX_BUFFER_SIZE,fp) && (strlen(line) != 0 )) {
! 1310: len = strlen(line);
! 1311: if(len > ANSWER_BEGIN_COLUMN ) {
! 1312: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
! 1313: sscanf(line,fmtbuf, login_item[count].student_number);
! 1314: login_item[count].answers = capa_malloc(num_q,1);
! 1315: sprintf(fmtbuf, "%%%dc",num_q);
! 1316: sscanf(line+ANSWER_BEGIN_COLUMN,fmtbuf, login_item[count].answers);
! 1317: count++;
! 1318: }
! 1319: }
! 1320: fclose(fp);
! 1321: return (count);
! 1322: }
! 1323:
! 1324: /*----------------------------------------------------------*/
! 1325: /* INPUT: option the option the check */
! 1326: /* set the X in dateX.db */
! 1327: /* section which section to check for */
! 1328: /* */
! 1329: /* OUTPUT: none */
! 1330: /* */
! 1331: /* RETURN: -2 invalid option */
! 1332: /* -1 capa_get_section_dates error */
! 1333: /* 0 no */
! 1334: /* 1 yes */
! 1335: /*----------------------------------------------------------*/
! 1336: int capa_check_option(int option,int set,int section)
! 1337: {
! 1338: T_dates* dates;
! 1339: int result;
! 1340:
! 1341: result=capa_get_section_dates(section,set,&dates);
! 1342: if (result < 0) return -1;
! 1343: switch(option) {
! 1344: case OPTION_INHIBIT_RESPONSE: result=dates->inhibit_response;break;
! 1345: case OPTION_VIEW_PROBLEMS_AFTER_DUE: result=dates->view_problems_after_due;break;
! 1346: default: result=-2;
! 1347: }
! 1348: capa_mfree((char*)dates);
! 1349: return result;
! 1350: }
! 1351:
! 1352: /*----------------------------------------------------------*/
! 1353: /* INPUT: set the X in logX.db */
! 1354: /* OUTPUT: none */
! 1355: /* */
! 1356: /* RETURN: -1 file error */
! 1357: /* 0 no login */
! 1358: /* >0 number of logins in that logX.db file */
! 1359: /*----------------------------------------------------------*/
! 1360: int
! 1361: compare_datetime(time,datetime)
! 1362: time_t time;
! 1363: char *datetime;
! 1364: {
! 1365: char dateStr[16], timeStr[16];
! 1366: time_t time2;
! 1367: char *t_ptr;
! 1368: int idx;
! 1369:
! 1370: /* sscanf(datetime,"%s %s",dateStr,timeStr); */
! 1371: t_ptr = index(datetime,' '); t_ptr++; /*** hpux complained */
! 1372: for(idx=0;idx<10;idx++) dateStr[idx] = datetime[idx];
! 1373: dateStr[10] = 0;
! 1374: for(idx=0;idx<5;idx++) timeStr[idx] = t_ptr[idx];
! 1375: timeStr[5] = 0;
! 1376: time2 = convertTime(dateStr,timeStr);
! 1377: if(time == time2 ) return (0);
! 1378: return ( (time > time2)? 1 : -1 );
! 1379: }
! 1380:
! 1381: /* --------------------------------- */
! 1382: /* check if records/dateX.db exists */
! 1383: /* read the section open date, answer date, due date info */
! 1384: /* What if: [7,3] date_info */
! 1385: /* [3,7] date_info */
! 1386: /* 4 date_info */
! 1387:
! 1388: int capa_check_date(int which,char *student_number, int section,int set)
! 1389: {
! 1390: int result;
! 1391: char date_str[TMP_LINE_LENGTH];
! 1392: time_t curtime;
! 1393:
! 1394: time(&curtime);
! 1395:
! 1396: result = capa_get_date(which,student_number,section,set,date_str);
! 1397: if ( result == 1 ) { result = compare_datetime(curtime,date_str); }
! 1398: return result;
! 1399: }
! 1400:
! 1401: time_t capa_convert_duration(char *duration)
! 1402: {
! 1403: int hour, minute;
! 1404: sscanf(duration,"%d:%d",&hour,&minute);
! 1405: return ((hour*60)+minute)*60;
! 1406: }
! 1407:
! 1408: void capa_get_due_date(char *date_str,T_dates *current,char *student_number,int set)
! 1409: {
! 1410: time_t duration=capa_convert_duration(current->duration);
! 1411: time_t duetime=0;
! 1412: time_t logintime;
! 1413: struct tm *due_time_tm;
! 1414: if ((duration > 0) && (student_number!=NULL)) {
! 1415: if (capa_get_login_time(student_number,set,&logintime)==1) {
! 1416: duetime=logintime+duration;
! 1417: due_time_tm=localtime(&duetime);
! 1418: sprintf(date_str,"%04d/%02d/%02d %02d:%02d",((due_time_tm->tm_year)+1900),
! 1419: due_time_tm->tm_mon+1,due_time_tm->tm_mday,due_time_tm->tm_hour,
! 1420: due_time_tm->tm_min);
! 1421: return;
! 1422: }
! 1423: }
! 1424: strncpy(date_str,current->due_date,DATE_BUFFER);
! 1425: }
! 1426:
! 1427: /* student_number can be NULL, if it isn't NULL it is used by get_due_date */
! 1428: /* to assign a due date based on the time the student first accessed the */
! 1429: /* set if duration is non-zero */
! 1430: int
! 1431: capa_get_date(int which,char *student_number,int section,int set,char *date_str)
! 1432: {
! 1433: T_dates *current;
! 1434: int result;
! 1435: result=capa_get_section_dates(section,set,¤t);
! 1436: if (result<0) return result;
! 1437: result=1;
! 1438: switch(which) {
! 1439: case CHECK_OPEN_DATE: strncpy(date_str,current->open_date,DATE_BUFFER); break;
! 1440: case CHECK_DUE_DATE: capa_get_due_date(date_str,current,student_number,set); break;
! 1441: case CHECK_ANS_DATE: strncpy(date_str,current->answer_date,DATE_BUFFER); break;
! 1442: default: strncpy(date_str,current->open_date,DATE_BUFFER); result=-4;break;
! 1443: }
! 1444: capa_mfree((char*)current);
! 1445: return result;
! 1446: }
! 1447:
! 1448: int
! 1449: capa_get_duration(char *student_number,int section,int set)
! 1450: {
! 1451: T_dates *current;
! 1452: int duration=0,result;
! 1453: result=capa_get_section_dates(section,set,¤t);
! 1454: if (result<0) return result;
! 1455: duration=capa_convert_duration(current->duration);
! 1456: capa_mfree((char*)current);
! 1457: return duration;
! 1458: }
! 1459:
! 1460: int
! 1461: capa_get_section_dates(int section,int set,T_dates** dates)
! 1462: {
! 1463: register int c;
! 1464: FILE *fp;
! 1465: int result = 0, done;
! 1466: int tmp_low, tmp_high, sec_mode;
! 1467: char filename[FILE_NAME_LENGTH], tmpline[TMP_LINE_LENGTH],
! 1468: default_line[TMP_LINE_LENGTH];
! 1469:
! 1470: sprintf(filename,"records/date%d.db",set);
! 1471: if( capa_access(filename, F_OK) != 0 ) { result = -2; } else {
! 1472: if ((fp=fopen(filename,"r")) == NULL) { result = -2; } else {
! 1473: done = 0; result = -3;
! 1474: /* first non-comment line is assumed to be the default line */
! 1475: c_gettype(fp); c_ignorewhite(fp); fgets(default_line,TMP_LINE_LENGTH-1,fp);
! 1476: do {
! 1477: c_ignorewhite(fp); c = getc(fp); ungetc(c,fp);
! 1478: if( c != EOF ) {
! 1479: sec_mode = c_getsec_range(fp,&tmp_low,&tmp_high);
! 1480: if( sec_mode > 0 ) { /* no error */
! 1481: c_ignorewhite(fp); fgets(tmpline,TMP_LINE_LENGTH-1,fp);
! 1482: if( sec_mode == 1 ) { /* form: sec date_info */
! 1483: if((result == -3) && (tmp_low == section)) {
! 1484: result=-4;
! 1485: *dates=add_date_info(tmp_low,tmp_low,tmpline);
! 1486: if ( *dates != NULL ) { done = 1; result = 1; }
! 1487: }
! 1488: } else { /* form : [low,high] date_info */
! 1489: if( (result == -3) && ((section>=tmp_low)&&(section<=tmp_high)) ) {
! 1490: result = -4;
! 1491: *dates=add_date_info(tmp_low,tmp_high,tmpline);
! 1492: if ( *dates != NULL ) { done = 1; result = 1; }
! 1493: }
! 1494: }
! 1495: } else { /* error in specify section date */
! 1496: while ( ((c = getc(fp)) != '\n') && ( c != EOF) ); /* skip to end of line */
! 1497: }
! 1498: } else { /* EOF encountered */
! 1499: done = 1;
! 1500: }
! 1501: } while (!done);
! 1502: /* need to deal with those sections not show up in the dateX.db file */
! 1503: if( result == -3 ) { /* section not in the dateX.db file, use default */
! 1504: result = -4;
! 1505: *dates=add_date_info(DATE_DEFAULTS,DATE_DEFAULTS,default_line);
! 1506: if ( *dates != NULL ) { result = 1; }
! 1507: }
! 1508: }
! 1509: fclose(fp);
! 1510: }
! 1511: return (result);
! 1512: }
! 1513:
! 1514: T_dates* add_date_info(int lowsec,int highsec, char *dateinfo)
! 1515: {
! 1516: T_dates *dates;
! 1517: int result;
! 1518: dates=(T_dates*)capa_malloc(sizeof(T_dates),1);
! 1519: result=sscanf(dateinfo,"%16c,%16c,%16c,%s %d,%d",dates->open_date,dates->due_date,
! 1520: dates->answer_date,dates->duration,&(dates->inhibit_response),
! 1521: &(dates->view_problems_after_due));
! 1522: if (result != 6) {
! 1523: capa_mfree((char*)dates);
! 1524: dates=NULL;
! 1525: } else {
! 1526: dates->section_start=lowsec;
! 1527: dates->section_end=highsec;
! 1528: dates->s_next=NULL;
! 1529: }
! 1530: return dates;
! 1531: }
! 1532: /*----------------------------------------------------------*/
! 1533: /* INPUT: set the X in dateX.db */
! 1534: /* dates a pointer to the dates pointer */
! 1535: /* ACTION: builds a linked list of T_dates containing */
! 1536: /* the login information */
! 1537: /* RETURN: <0 file error */
! 1538: /* >0 success (number of lines successfully */
! 1539: /* proccessed) */
! 1540: /*----------------------------------------------------------*/
! 1541: int capa_get_all_dates (int set,T_dates **dates)
! 1542: {
! 1543: T_dates *current;
! 1544: FILE *fp;
! 1545: int result = 0, done, tmp_low, tmp_high, sec_mode, c, num=0;
! 1546: char filename[FILE_NAME_LENGTH], tmpline[TMP_LINE_LENGTH];
! 1547:
! 1548: sprintf(filename,"records/date%d.db",set);
! 1549: if ( ((fp=fopen(filename,"r")) == NULL)) { result = -2; } else {
! 1550: done = 0; result = -3;
! 1551: /* first non-comment line is assumed to be the default line */
! 1552: c_gettype(fp); c_ignorewhite(fp); fgets(tmpline,TMP_LINE_LENGTH-1,fp);
! 1553: *dates=add_date_info(DATE_DEFAULTS,DATE_DEFAULTS,tmpline);
! 1554: num++;
! 1555: if ( NULL == (current=*dates) ) {
! 1556: result = -3;
! 1557: } else {
! 1558: while(1) {
! 1559: c_ignorewhite(fp); c = getc(fp); ungetc(c,fp);
! 1560: if( c == EOF ) { break; }
! 1561: sec_mode = c_getsec_range(fp,&tmp_low,&tmp_high);
! 1562: if( sec_mode > 0 ) { /* no error */
! 1563: c_ignorewhite(fp); fgets(tmpline,TMP_LINE_LENGTH-1,fp);
! 1564: if( sec_mode == 1 ) { /* form: sec date_info */
! 1565: current->s_next=add_date_info(tmp_low,tmp_low,tmpline);
! 1566: } else { /* form : [low,high] date_info */
! 1567: current->s_next=add_date_info(tmp_low,tmp_high,tmpline);
! 1568: }
! 1569: current=current->s_next;
! 1570: num++;
! 1571: } else { /* error in specify section date */
! 1572: while ( ((c = getc(fp)) != '\n') && ( c != EOF) ); /* skip to end of line */
! 1573: }
! 1574: }
! 1575: result=num;
! 1576: }
! 1577: fclose(fp);
! 1578: }
! 1579: return (result);
! 1580: }
! 1581:
! 1582: /*----------------------------------------------------------*/
! 1583: /* INPUT: dates a pointer to the dates pointer */
! 1584: /* ACTION: frees a linked list of T_dates */
! 1585: /*----------------------------------------------------------*/
! 1586: void free_dates(T_dates *dates)
! 1587: {
! 1588: T_dates *current = dates,*next;
! 1589: while ( current != NULL ) {
! 1590: next = current->s_next;
! 1591: capa_mfree((char*)current);
! 1592: current = next;
! 1593: }
! 1594: }
! 1595:
! 1596: /*----------------------------------------------------------*/
! 1597: /* INPUT: set the X in dateX.db */
! 1598: /* dates a pointer to the dates pointer */
! 1599: /* ACTION: takes a linked list of date information and */
! 1600: /* and writes the info to a file */
! 1601: /* RETURN: -1 file error */
! 1602: /* 1 success */
! 1603: /*----------------------------------------------------------*/
! 1604: int capa_set_all_dates (int set,T_dates *dates)
! 1605: {
! 1606: T_dates *current = dates;
! 1607: int result;
! 1608: FILE* fp;
! 1609: char filename[FILE_NAME_LENGTH];
! 1610:
! 1611: sprintf(filename,"records/date%d.db",set);
! 1612: if ( ((fp=fopen(filename,"w")) == NULL) ) { result = -1; } else {
! 1613: result=1;
! 1614: while ( current != NULL ) {
! 1615: if ( current->section_start == DATE_DEFAULTS ) {
! 1616: fprintf(fp,"<< DEFAULTS >> ");
! 1617: } else {
! 1618: fprintf(fp,"[%d, %d] ", current->section_start,current->section_end);
! 1619: }
! 1620: fprintf(fp,"%s,%s,%s,%s %d,%d\n", current->open_date,current->due_date,
! 1621: current->answer_date,current->duration,current->inhibit_response,
! 1622: current->view_problems_after_due);
! 1623: current = current->s_next;
! 1624: }
! 1625: fclose(fp);
! 1626: }
! 1627: return result;
! 1628: }
! 1629:
! 1630: /*----------------------------------------------------------*/
! 1631: /* INPUT: set the X in logX.db */
! 1632: /* OUTPUT: none */
! 1633: /* */
! 1634: /* RETURN: -1 file error */
! 1635: /* 0 no login */
! 1636: /* >0 number of logins in that logX.db file */
! 1637: /*----------------------------------------------------------*/
! 1638:
! 1639: #define FIFTEEN_MINUTES (15*60)
! 1640: #define TEN_MINUTES (600)
! 1641: #define ONE_DAY (86400)
! 1642: int /* RETURNS: 1 first time login, 2 second time login, 0 not ok, -1 file error */
! 1643: login_check(student_number) /* ARGUMENTS: */
! 1644: char *student_number; /* Student # */
! 1645: { /* LOCALS: */
! 1646: FILE *fp;
! 1647:
! 1648: int errcode=0;
! 1649: int found;
! 1650: char filename[FILE_NAME_LENGTH];
! 1651: char line[SMALL_LINE_BUFFER], new_line[SMALL_LINE_BUFFER];
! 1652: struct tm *theDT;
! 1653: time_t login_time, record_time;
! 1654: long offsetL, offsetR, offsetEnd,left_leng;
! 1655: char s_number[MAX_STUDENT_NUMBER+1];
! 1656: char tty_name[FILE_NAME_LENGTH];
! 1657: int log_tries, p_id;
! 1658: int month, day, year, hour, min, sec;
! 1659: char *tmp_buffer;
! 1660:
! 1661: sprintf(filename,"records/active.log");
! 1662:
! 1663: if( capa_access(filename,F_OK) < 0 ) { /*<------------- File not exist */
! 1664: if ((fp=fopen(filename,"w"))==NULL) { /* create if non-existant */
! 1665: /*printf("Error: can't create %s\n",filename);*/
! 1666: return (-1);
! 1667: }
! 1668: fclose(fp);
! 1669: }
! 1670: if ((fp=fopen(filename,"r"))==NULL) {
! 1671: /*printf("Error: can't open %s\n",filename);*/
! 1672: return (-1);
! 1673: }
! 1674: flockstream(fp); /* lock exclusively and perform read/write operation */
! 1675:
! 1676: found = 0;
! 1677: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
! 1678: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
! 1679: }
! 1680: offsetR = ftell(fp);
! 1681: offsetL = offsetR - strlen(line);
! 1682: funlockstream(fp); fclose(fp);
! 1683:
! 1684: if( found && (strlen(line) != 0) ) {
! 1685: /* printf("FOUND:%slen=%d\n",line,strlen(line)); */
! 1686: sscanf(line,"%s , %d , %d , /dev/%s ,(%d/%d/%d %d:%d:%d)\n", s_number,&log_tries,&p_id,tty_name,&month,&day,&year,&hour,&min,&sec);
! 1687: record_time = time(NULL);
! 1688: theDT = localtime(&record_time);
! 1689: theDT->tm_sec = sec; theDT->tm_min = min;
! 1690: theDT->tm_hour = hour; theDT->tm_mday = day;
! 1691: theDT->tm_mon = month-1; theDT->tm_year = year;
! 1692: theDT->tm_wday = weekday(year,month,day);
! 1693: theDT->tm_yday = julianday(year,month,day);
! 1694: record_time = mktime( theDT );
! 1695: time(&login_time); theDT = localtime(&login_time);
! 1696: switch(log_tries) {
! 1697: case 0: log_tries = 1; errcode = 1; break;
! 1698: case 1: log_tries = 2; errcode = 2;
! 1699: break;
! 1700: case 2: log_tries = 3; errcode = 0; break;
! 1701: case 3: if( (login_time - record_time) >= TEN_MINUTES ) {
! 1702: log_tries = 1; errcode = 1;
! 1703: } else {
! 1704: log_tries = 3; errcode = 2;
! 1705: return (0);
! 1706: }
! 1707: break;
! 1708: default: printf("ERROR: Number of logins UNKNOWN\n");
! 1709: log_tries = 1; errcode = 1;
! 1710: break;
! 1711: }
! 1712: sprintf(new_line,"%s , %2d , %5d , %s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", student_number, log_tries, getpid(),ttyname(0), theDT->tm_mon + 1, theDT->tm_mday, theDT->tm_year, theDT->tm_hour, theDT->tm_min ,theDT->tm_sec);
! 1713: if ((fp=fopen(filename,"r+"))==NULL) {
! 1714: /*printf("Error: can't open %s\n",filename);*/
! 1715: return (-1);
! 1716: }
! 1717: flockstream(fp);
! 1718: tmp_buffer = (char *)malloc(8*1024*56);
! 1719: found = 0;
! 1720: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
! 1721: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
! 1722: }
! 1723: offsetR = ftell(fp); offsetL = offsetR - strlen(line);
! 1724: fseek(fp,0L,SEEK_END); offsetEnd = ftell(fp);
! 1725: left_leng = offsetEnd - offsetR;
! 1726: fseek(fp,offsetR,SEEK_SET);
! 1727: left_leng = fread(tmp_buffer, 1, left_leng+1, fp);
! 1728: tmp_buffer[left_leng] = 0;
! 1729: fseek(fp,offsetL,SEEK_SET);
! 1730: if ( fprintf(fp,"%s%s",new_line,tmp_buffer) < 0 ) {
! 1731: /*printf("Error: cannot write active.log\n");*/
! 1732: errcode = -1;
! 1733: }
! 1734: fflush(fp);
! 1735: free( (char *)tmp_buffer);
! 1736: funlockstream(fp);
! 1737: fclose(fp);
! 1738: } else { /********************************** First time login */
! 1739: if ((fp=fopen(filename,"a+"))==NULL) {
! 1740: /*printf("Error: can't open %s\n",filename);*/
! 1741: return (-1);
! 1742: }
! 1743: log_tries = 1;
! 1744: time(&login_time);
! 1745: theDT = localtime(&login_time);
! 1746: sprintf(line,"%s , %2d , %5d , %s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", student_number, log_tries, getpid(),ttyname(0), theDT->tm_mon + 1, theDT->tm_mday, theDT->tm_year, theDT->tm_hour, theDT->tm_min ,theDT->tm_sec);
! 1747: /*
! 1748: leng = strlen(line);
! 1749: for(idx = 0, len_idx = 0; idx<(leng-1); idx++) {
! 1750: if(line[idx] == '\n' && line[idx+1] == '\n') {
! 1751: line[idx+1] = 0;
! 1752: }
! 1753: }
! 1754: */
! 1755: flockstream(fp);
! 1756: if ( !fwrite((char *)line, strlen(line), 1, fp) ) {
! 1757: /*printf("ERROR: cannot write active.log\n");*/
! 1758: errcode = -1;
! 1759: } else {
! 1760: errcode = 1;
! 1761: }
! 1762: fflush(fp);
! 1763: funlockstream(fp);
! 1764: fclose(fp);
! 1765: }
! 1766: return (errcode);
! 1767:
! 1768: }
! 1769:
! 1770: /******************************************************************************/
! 1771: /* Logout check */
! 1772: /******************************************************************************/
! 1773: int /* RETURNS: 1 successful, 0 otherwise, -1 file error */
! 1774: logout_check(student_number) /* ARGUMENTS: */
! 1775: char *student_number; /* Student # */
! 1776: { /* LOCALS: */
! 1777: FILE *fp;
! 1778:
! 1779: int errcode=0;
! 1780: int found;
! 1781: char filename[FILE_NAME_LENGTH];
! 1782: char line[SMALL_LINE_BUFFER];
! 1783: long offsetL, offsetR, offsetEnd,left_leng;
! 1784: char s_number[MAX_STUDENT_NUMBER+1];
! 1785: char tty_name[FILE_NAME_LENGTH];
! 1786: int log_tries, p_id;
! 1787: int month, day, year, hour, min, sec;
! 1788: char *tmp_buffer;
! 1789:
! 1790:
! 1791: sprintf(filename,"records/active.log");
! 1792: if ((fp=fopen(filename,"r"))==NULL) {
! 1793: /*printf("Error: can't open %s\n",filename);*/
! 1794: return (-1);
! 1795: }
! 1796: flockstream(fp); /* lock exclusively and perform read/write operation */
! 1797:
! 1798: found = 0;
! 1799: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
! 1800: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
! 1801: }
! 1802: offsetR = ftell(fp);
! 1803: offsetL = offsetR - strlen(line);
! 1804:
! 1805: funlockstream(fp);
! 1806: fclose(fp);
! 1807:
! 1808: if( found ) {
! 1809: #ifdef __alpha
! 1810: sscanf(line,"%s , %d , %d , /dev/%s ,(%d/%d/%d %d:%d:%d)\n", s_number,&log_tries,&p_id,tty_name,&month,&day,&year,&hour,&min,&sec);
! 1811: #else
! 1812: sscanf(line,"%s , %d , %d , /dev/%s ,(%d/%d/%d %d:%d:%d)\n", \
! 1813: s_number,&log_tries,&p_id,tty_name,&month,&day,&year,&hour,&min,&sec);
! 1814: #endif
! 1815: switch(log_tries) {
! 1816: case 0: log_tries = 0;
! 1817: break;
! 1818: case 1: log_tries = 0;
! 1819: break;
! 1820: case 2: log_tries = 0;
! 1821: break;
! 1822: default: printf("ERROR: Number of logins UNKNOWN\n");
! 1823: log_tries = 0;
! 1824: break;
! 1825: }
! 1826: #ifdef __alpha
! 1827: sprintf(line,"%s , %2d , %5d , /dev/%s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", s_number,log_tries, p_id, tty_name, month, day, year, hour, min, sec);
! 1828: #else
! 1829: sprintf(line,"%s , %2d , %5d , /dev/%s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", \
! 1830: s_number,log_tries, p_id, tty_name, month, day, year, hour, min, sec);
! 1831: #endif
! 1832:
! 1833: if ((fp=fopen(filename,"r+"))==NULL) {
! 1834: /*printf("Error: can't open %s\n",filename);*/
! 1835: return (-1);
! 1836: }
! 1837: flockstream(fp);
! 1838: tmp_buffer = (char *)malloc(8*1024*56);
! 1839: fseek(fp,0L,SEEK_END);
! 1840: offsetEnd = ftell(fp);
! 1841: left_leng = offsetEnd - offsetR;
! 1842: fseek(fp,offsetR,SEEK_SET);
! 1843: fread(tmp_buffer, left_leng, 1, fp);
! 1844: tmp_buffer[left_leng] = 0;
! 1845: /*
! 1846: for(idx=0, l_idx = 0; idx< (left_leng-1); idx++) {
! 1847: if( tmp_buffer[idx] == '/n' && tmp_buffer[idx+1] == '/n' ) {
! 1848: }
! 1849: }
! 1850: */
! 1851: fseek(fp,offsetL,SEEK_SET);
! 1852: if ( fprintf(fp,"%s%s",line,tmp_buffer) < 0 ) {
! 1853: /*printf("Error: write error\n");*/
! 1854: errcode = -1;
! 1855: } else {
! 1856: errcode = 1;
! 1857: }
! 1858: fflush(fp);
! 1859: free( (char *)tmp_buffer);
! 1860: funlockstream(fp);
! 1861: fclose(fp);
! 1862: } else {
! 1863: errcode = -1;
! 1864: }
! 1865: return (errcode);
! 1866:
! 1867: }
! 1868: /*********************************************/
! 1869: /* SIZE of char =1, int=4, long=4, double=8 */
! 1870: void
! 1871: capa_seed(seed1,seed2,student_number)long *seed1;long *seed2;char *student_number;
! 1872: {
! 1873: int class_pin1, class_pin2;
! 1874: int s_pin1, s_pin2, s_pin3;
! 1875: int i;
! 1876: char dest[16], tmpSN[MAX_STUDENT_NUMBER+1];
! 1877: char *class,*capadefault="capadefault";
! 1878: long part1, part2;
! 1879: #if defined(NeXT)
! 1880: char cwd[FILE_NAME_LENGTH];
! 1881: #endif
! 1882: int big_endian;
! 1883:
! 1884: big_endian = endian(); /* determine what type of CPU we are on */
! 1885:
! 1886: #if defined(NeXT)
! 1887: class = getwd(cwd);
! 1888: if( class == NULL ) { class = cwd; }
! 1889: #else
! 1890: class = getcwd(NULL,255);
! 1891: #endif
! 1892: class_pin1 = class_pin2 = 2;
! 1893: s_pin1 = s_pin2 = s_pin3 = 2;
! 1894:
! 1895: if( class == NULL ) {
! 1896: printf("capa_seed(): Current working directory unknown! Using capadefault\n");
! 1897: class=capa_malloc(strlen(capadefault)+1,1);
! 1898: strcpy(class,capadefault);
! 1899: }
! 1900: if( big_endian ) {
! 1901: for(i=0;i<4;i++) dest[i] = class[strlen(class)-8+i];
! 1902: for(i=4;i<8;i++) dest[i] = 0;
! 1903: memcpy((char *)(&class_pin1), dest, 4);
! 1904: for(i=0;i<4;i++) dest[i] = class[strlen(class)-4+i];
! 1905: for(i=4;i<8;i++) dest[i] = 0;
! 1906: memcpy((char *)(&class_pin2), dest, 4);
! 1907: } else {
! 1908: for(i=0;i<4;i++) dest[i] = class[strlen(class)-i-5];
! 1909: for(i=4;i<8;i++) dest[i] = 0;
! 1910: memcpy((char *)(&class_pin1), dest, 4);
! 1911: for(i=0;i<4;i++) dest[i] = class[strlen(class)-i-1];
! 1912: for(i=4;i<8;i++) dest[i] = 0;
! 1913: memcpy((char *)(&class_pin2), dest, 4);
! 1914: }
! 1915: for(i=0;i<MAX_STUDENT_NUMBER;i++) {
! 1916: if(islower(student_number[i])) {
! 1917: tmpSN[i] = toupper(student_number[i]);
! 1918: } else {
! 1919: tmpSN[i] = student_number[i];
! 1920: }
! 1921: }
! 1922: tmpSN[MAX_STUDENT_NUMBER] = 0;
! 1923:
! 1924: if( big_endian ) { /* big endian ** SUN, BlackNeXT 68xxx , PowerPC */
! 1925: for(i=0;i<4;i++) dest[i] = tmpSN[i];
! 1926: for(i=4;i<8;i++) dest[i] = 0;
! 1927: memcpy((char *)(&s_pin1), dest, 4); /* 012345678 -> "0123" */
! 1928: for(i=0;i<4;i++) dest[i] = tmpSN[i+2];
! 1929: for(i=4;i<8;i++) dest[i] = 0;
! 1930: memcpy((char *)(&s_pin2), dest, 4); /* 012345678 -> "2345" */
! 1931: for(i=0;i<4;i++) dest[i] = tmpSN[i+5];
! 1932: for(i=4;i<8;i++) dest[i] = 0;
! 1933: memcpy((char *)(&s_pin3), dest, 4); /* 012345678 -> "5678" */
! 1934: } else { /* Intel 386, 486 */
! 1935: for(i=0;i<4;i++) dest[i] = tmpSN[3-i];
! 1936: for(i=4;i<8;i++) dest[i] = 0;
! 1937: memcpy((char *)(&s_pin1), dest, 4); /* 012345678 -> "0123" */
! 1938: for(i=0;i<4;i++) dest[i] = tmpSN[5-i];
! 1939: for(i=4;i<8;i++) dest[i] = 0;
! 1940: memcpy((char *)(&s_pin2), dest, 4); /* 012345678 -> "2345" */
! 1941: for(i=0;i<4;i++) dest[i] = tmpSN[8-i];
! 1942: for(i=4;i<8;i++) dest[i] = 0;
! 1943: memcpy((char *)(&s_pin3), dest, 4); /* 012345678 -> "5678" */
! 1944: }
! 1945:
! 1946:
! 1947: part1 = s_pin1 + s_pin3+ class_pin2; if(part1 < 0) part1 = part1 * (-1);
! 1948: part2 = s_pin2 + class_pin1; if(part2 < 0) part2 = part2 * (-1);
! 1949:
! 1950: #ifdef SEED_DBG
! 1951: printf("S_PIN(%d,%d, %d) C_PIN(%d,%d)\n",s_pin1, s_pin2, s_pin3, class_pin1, class_pin2);
! 1952: printf("SEED(%ld,%ld)\n",part1, part2);
! 1953: #endif
! 1954: {
! 1955: extern void gsrgs(long getset,long *qvalue);
! 1956: static long qrgnin;
! 1957: gsrgs(0L,&qrgnin);
! 1958: if(!qrgnin)
! 1959: setall(part1, part2);
! 1960: }
! 1961: (*seed1) = part1;
! 1962: (*seed2) = part2;
! 1963: free(class);
! 1964: }
! 1965: /* ======================================================= PIN number */
! 1966: /* pin should only called once for each student. */
! 1967: /* if not called at the beginning of problem set, try to call it automatically */
! 1968:
! 1969: int /* RETURNS: pin number for login set */
! 1970: capa_PIN(student_number, set, guess) /* ARGUMENTS: */
! 1971: char *student_number;
! 1972: int set; /* Problem set number */
! 1973: int guess;
! 1974: { /* LOCALS: */
! 1975: int current=0, /* Current pin for set */
! 1976: i,j, /* Array indices */
! 1977: nope,
! 1978: correct=0,
! 1979: all_pins[ONE_K];
! 1980: long part1, part2;
! 1981: long orig_gen, new_gen;
! 1982:
! 1983: capa_seed(&part1, &part2, student_number);
! 1984: gscgn(GET_GENERATOR, &orig_gen);
! 1985: new_gen = PIN_G;
! 1986: gscgn(SET_GENERATOR, &new_gen);
! 1987: setsd(part1, part2);
! 1988: /* Generate 4-digit pin (1000-9999) */
! 1989: for (i=1; i<=set; i++) {
! 1990: current=1000+ignlgi()%9000;
! 1991: do {
! 1992: nope=0;
! 1993: for (j=1; j<i; j++) {
! 1994: if (current == all_pins[j]) {
! 1995: current=1000+ignlgi()%9000;
! 1996: nope++;
! 1997: }
! 1998: }
! 1999: } while (nope);
! 2000: all_pins[i]=current;
! 2001: if (guess && guess==current) correct=i;
! 2002: }
! 2003: gscgn(SET_GENERATOR, &orig_gen);
! 2004: if (guess) return (correct);
! 2005: return (current);
! 2006: }
! 2007:
! 2008: /* -------------------------------------------------------------------- */
! 2009: /* returns a longer pin, the first four characters are the same as the */
! 2010: /* normal capaId, additionally the result is a capa_malloc string */
! 2011: /* containing the number */
! 2012: /* NOTE!-> the result is a string of letters where A=1..I=9,J=0 */
! 2013: /* -------------------------------------------------------------------- */
! 2014: char*
! 2015: capa_id_plus(student_number, set, plus)
! 2016: char *student_number;
! 2017: int set;
! 2018: int plus;
! 2019: {
! 2020: long part1,part2,orig_gen,new_gen,pin,rout,k,i;
! 2021: char *result;
! 2022: char letters[10]={'J','A','B','C','D','E','F','G','H','I'};
! 2023: capa_seed(&part1, &part2, student_number);
! 2024: gscgn(GET_GENERATOR, &orig_gen);
! 2025: new_gen = PIN_G;
! 2026: gscgn(SET_GENERATOR, &new_gen);
! 2027: setsd(part1, part2);
! 2028: pin=capa_PIN(student_number,set,0);
! 2029: result=(char *)capa_malloc(sizeof(char), plus+MAX_PIN_CHAR+1);
! 2030: k=1;
! 2031: for(i=1;i<=MAX_PIN_CHAR;i++) {
! 2032: result[MAX_PIN_CHAR-i] = letters[(pin%(k*10))/k];
! 2033: k*=10;
! 2034: }
! 2035: for(i=MAX_PIN_CHAR;i<MAX_PIN_CHAR+plus;i++) {
! 2036: rout = ignlgi()%10;
! 2037: result[i] = letters[rout];
! 2038: }
! 2039: result[i] = '\0';
! 2040: gscgn(SET_GENERATOR, &orig_gen);
! 2041: return result;
! 2042: }
! 2043: /* -------------------------------------------------------------------- */
! 2044: /* need to set problem_p = NULL after this call */
! 2045: /* -------------------------------------------------------------------- */
! 2046: void
! 2047: free_problems(problem_p) Problem_t *problem_p;
! 2048: {
! 2049: Problem_t *p, *next;
! 2050:
! 2051: for (p=problem_p; p!=NULL ; p=next) {
! 2052: next=p->next;
! 2053: if (p->question != NULL) capa_mfree(p->question);
! 2054: if (p->answer != NULL) capa_mfree(p->answer);
! 2055: if (p->ans_cnt > 1 ) { AnswerInfo_t *a,*b;
! 2056: for(a = p->ans_list; a != NULL ; a = b) {
! 2057: b = a->ans_next;
! 2058: if (a->ans_str != NULL) capa_mfree(a->ans_str);
! 2059: if (a->ans_id_list != NULL ) capa_mfree(a->ans_id_list);
! 2060: if (a->ans_pts_list) {
! 2061: free_ptslist(a->ans_pts_list);
! 2062: }
! 2063: if (a->ans_unit) {
! 2064: freelist_unit_e(a->ans_unit->u_list);
! 2065: if (a->ans_unit != NULL) capa_mfree((char *)a->ans_unit);
! 2066: }
! 2067: capa_mfree((char *)a);
! 2068: }
! 2069: }
! 2070: if (p->id_list != NULL ) capa_mfree(p->id_list);
! 2071: if (p->pts_list!= NULL ) {
! 2072: free_ptslist(p->pts_list);
! 2073: }
! 2074: if (p->hint != NULL ) capa_mfree(p->hint);
! 2075: if (p->explain != NULL ) capa_mfree(p->explain);
! 2076: if (p->ans_unit !=NULL ) {
! 2077: freelist_unit_e(p->ans_unit->u_list);
! 2078: capa_mfree((char *)p->ans_unit);
! 2079: }
! 2080: capa_mfree((char *)p);
! 2081: p=NULL;
! 2082: }
! 2083: problem_p=NULL;
! 2084: }
! 2085:
! 2086: /******************************************************************************/
! 2087: /* PARSE SOURCE FILE AND RETURN BLOCKS OF TEXT */
! 2088: /******************************************************************************/
! 2089: int
! 2090: capa_parse(set,problem,student_number,num_questions,func_ptr)
! 2091: int set;Problem_t **problem;char *student_number;int *num_questions;
! 2092: void (*func_ptr)();
! 2093: {
! 2094: char filename[QUARTER_K];
! 2095: int errcode;
! 2096: FILE *fp;
! 2097: extern FILE *Input_stream[MAX_OPENED_FILE];
! 2098: extern char Opened_filename[MAX_OPENED_FILE][QUARTER_K];
! 2099: extern int Lexi_line;
! 2100: extern int Lexi_qnum;
! 2101: extern Problem_t *FirstProblem_p;
! 2102: extern Problem_t *LastProblem_p;
! 2103: extern Problem_t *LexiProblem_p;
! 2104: extern char *StartText_p;
! 2105: extern char *EndText_p;
! 2106: extern char *ErrorMsg_p;
! 2107: extern int ErrorMsg_count;
! 2108: extern char Parse_class[QUARTER_K];
! 2109: extern int Parse_section;
! 2110: extern int Parse_set;
! 2111: extern char Parse_name[MAX_NAME_CHAR+1];
! 2112: extern char Parse_student_number[MAX_STUDENT_NUMBER+1];
! 2113: extern int Symb_count;
! 2114: extern int first_run;
! 2115: extern int Stop_Parser;
! 2116: extern void (*Status_Func)();
! 2117: long seed1, seed2;
! 2118: T_student a_student;
! 2119: char *class, *classname, warn_msg[WARN_MSG_LENGTH];
! 2120: #if defined(NeXT)
! 2121: char cwd[FILE_NAME_LENGTH];
! 2122:
! 2123: class = getwd(cwd);
! 2124: if( class == NULL ) { class = cwd; }
! 2125: #else
! 2126: class = getcwd(NULL,255);
! 2127:
! 2128: #endif
! 2129:
! 2130: if(class == NULL) { /* printf("capa_parse(): Current working directory unknown!"); */ return (-1); }
! 2131: classname = rindex(class,'/'); classname++; /*** hpux complained */
! 2132: sprintf(Parse_class,"%s", classname);
! 2133: free(class);
! 2134: if( capa_get_student(student_number, &a_student) < 1 ) {
! 2135: /*printf("Error: capa_parse() encountered a student which is not in classl file\n"); */
! 2136: return (-1);
! 2137: }
! 2138: sprintf(filename,"capa.config");
! 2139: if ((fp=fopen(filename,"r"))==NULL) {
! 2140: /* printf("Error: can't open %s\n",filename);*/
! 2141: return (-1);
! 2142: }
! 2143: u_getunit(fp);
! 2144: fclose(fp);
! 2145: strncpy(Parse_name,a_student.s_nm,MAX_NAME_CHAR+1);
! 2146: strncpy(Parse_student_number,student_number,MAX_STUDENT_NUMBER+1);
! 2147: Parse_section = a_student.s_sec;
! 2148: if(ErrorMsg_p) { capa_mfree(ErrorMsg_p); ErrorMsg_p = NULL; }
! 2149: if(EndText_p) { capa_mfree(EndText_p); EndText_p = NULL; }
! 2150: if(StartText_p) { capa_mfree(StartText_p); StartText_p = NULL; }
! 2151: ErrorMsg_p = NULL; first_run = 1; EndText_p = NULL;
! 2152: free_symtree(); Symb_count = ErrorMsg_count = Lexi_line = Lexi_qnum = 0;
! 2153: FirstProblem_p = LastProblem_p = NULL;
! 2154: LexiProblem_p = (Problem_t *)capa_malloc(sizeof(Problem_t),1);
! 2155: problem_default(LexiProblem_p);
! 2156: /*LexiProblem_p->capaidplus=NULL;*/
! 2157: Parse_set = set;
! 2158: Status_Func=func_ptr;
! 2159: sprintf(filename,"set%d.qz",set);
! 2160: #ifdef AVOIDYYINPUT
! 2161: yyin=fopen(filename,"r");
! 2162: #else
! 2163: if ( (Input_stream[0]=fopen(filename,"r")) == NULL) {
! 2164: /* printf("Error: can't open %s\n",filename);*/
! 2165: sprintf(warn_msg,"capa_parse(): CANNOT OPEN FILE\"%s\", file does not exist or is not readable.\n", filename);
! 2166: capa_msg(MESSAGE_ERROR,warn_msg);
! 2167: return (-1);
! 2168: }
! 2169: #endif
! 2170: sprintf(Opened_filename[0],"%s",filename);
! 2171:
! 2172: capa_seed(&seed1, &seed2, student_number); setall(seed1,seed2);
! 2173:
! 2174: yyrestart(yyin);
! 2175: Stop_Parser=0;
! 2176: if ( !yyparse() ) { errcode = Lexi_qnum; } else { errcode = 0; }
! 2177: /* fclose(Input_stream[0]);*/ /* The Lexer handles closing this */
! 2178: /* print_symb_stat(); */
! 2179: free_symtree();
! 2180: /*
! 2181: capa_mfree((char *)LexiProblem_p);
! 2182: LexiProblem_p = NULL;
! 2183: */
! 2184: (*problem) = FirstProblem_p;
! 2185: (*num_questions) = Lexi_qnum;
! 2186: return (errcode);
! 2187: }
! 2188:
! 2189: /******************************************************************************/
! 2190: /* PARSE SOURCE FILE AND RETURN BLOCKS OF TEXT, unlike capa_parse_student */
! 2191: /******************************************************************************/
! 2192: int
! 2193: capa_parse_student(set,problem,a_student,num_questions,func_ptr)
! 2194: int set;Problem_t **problem;T_student *a_student;int *num_questions;
! 2195: void (*func_ptr)();
! 2196: {
! 2197: char filename[QUARTER_K];
! 2198: int errcode;
! 2199: FILE *fp;
! 2200: extern FILE *Input_stream[MAX_OPENED_FILE];
! 2201: extern char Opened_filename[MAX_OPENED_FILE][QUARTER_K];
! 2202: extern int Lexi_line;
! 2203: extern int Lexi_qnum;
! 2204: extern Problem_t *FirstProblem_p;
! 2205: extern Problem_t *LastProblem_p;
! 2206: extern Problem_t *LexiProblem_p;
! 2207: extern char *StartText_p;
! 2208: extern char *EndText_p;
! 2209: extern char *ErrorMsg_p;
! 2210: extern int ErrorMsg_count;
! 2211: extern char Parse_class[QUARTER_K];
! 2212: extern int Parse_section;
! 2213: extern int Parse_set;
! 2214: extern char Parse_name[MAX_NAME_CHAR+1];
! 2215: extern char Parse_student_number[MAX_STUDENT_NUMBER+1];
! 2216: extern int Symb_count;
! 2217: extern int first_run;
! 2218: extern void (*Status_Func)();
! 2219: long seed1, seed2;
! 2220: char *class, *classname, warn_msg[WARN_MSG_LENGTH];
! 2221:
! 2222: #if defined(NeXT)
! 2223: char cwd[FILE_NAME_LENGTH];
! 2224:
! 2225: class = getwd(cwd);
! 2226: if( class == NULL ) { class = cwd; }
! 2227: #else
! 2228: class = getcwd(NULL,255);
! 2229:
! 2230: #endif
! 2231:
! 2232: if(class == NULL) { /* printf("capa_parse(): Current working directory unknown!"); */ return (-1); }
! 2233: classname = rindex(class,'/'); classname++; /*** hpux complained */
! 2234: sprintf(Parse_class,"%s", classname);
! 2235: free(class);
! 2236:
! 2237: sprintf(filename,"capa.config");
! 2238: if ((fp=fopen(filename,"r"))==NULL) {
! 2239: /* printf("Error: can't open %s\n",filename);*/
! 2240: sprintf(warn_msg,"capa_parse(): CANNOT OPEN FILE\"%s\", file does not exist or is not readable.\n", filename);
! 2241: capa_msg(MESSAGE_ERROR,warn_msg);
! 2242: return (-1);
! 2243: }
! 2244: u_getunit(fp);
! 2245: fclose(fp);
! 2246: strncpy(Parse_name,a_student->s_nm,MAX_NAME_CHAR+1);
! 2247: strncpy(Parse_student_number,a_student->s_sn,MAX_STUDENT_NUMBER+1);
! 2248: Parse_section = a_student->s_sec;
! 2249: if(ErrorMsg_p) { capa_mfree(ErrorMsg_p); ErrorMsg_p = NULL; }
! 2250: if(EndText_p) { capa_mfree(EndText_p); EndText_p = NULL; }
! 2251: if(StartText_p) { capa_mfree(StartText_p); StartText_p = NULL; }
! 2252: ErrorMsg_p = NULL; first_run = 1; EndText_p = NULL;
! 2253: free_symtree(); Symb_count = ErrorMsg_count = Lexi_line = Lexi_qnum = 0;
! 2254: FirstProblem_p = LastProblem_p = NULL;
! 2255: LexiProblem_p = (Problem_t *)capa_malloc(sizeof(Problem_t),1);
! 2256: problem_default(LexiProblem_p);
! 2257: /*LexiProblem_p->capaidplus=NULL;*/
! 2258: Parse_set = set;
! 2259: Status_Func=func_ptr;
! 2260: sprintf(filename,"set%d.qz",set);
! 2261: #ifdef AVOIDYYINPUT
! 2262: yyin=fopen(filename,"r");
! 2263: #else
! 2264: if ( (Input_stream[0]=fopen(filename,"r")) == NULL) {
! 2265: /* printf("Error: can't open %s\n",filename);*/
! 2266: sprintf(warn_msg,"capa_parse(): CANNOT OPEN FILE\"%s\", file does not exist or is not readable.\n", filename);
! 2267: capa_msg(MESSAGE_ERROR,warn_msg);
! 2268: return (-1);
! 2269: }
! 2270: #endif
! 2271: sprintf(Opened_filename[0],"%s",filename);
! 2272:
! 2273: capa_seed(&seed1, &seed2, a_student->s_sn); setall(seed1,seed2);
! 2274:
! 2275: yyrestart(yyin);
! 2276: if ( !yyparse() ) { errcode = Lexi_qnum; } else { errcode = 0; }
! 2277: /* fclose(Input_stream[0]);*/ /*The Lexer handles closing this*/
! 2278: /* print_symb_stat(); */
! 2279: free_symtree();
! 2280: /*
! 2281: capa_mfree((char *)LexiProblem_p);
! 2282: LexiProblem_p = NULL;
! 2283: */
! 2284: (*problem) = FirstProblem_p;
! 2285: (*num_questions) = Lexi_qnum;
! 2286: return (errcode);
! 2287: }
! 2288:
! 2289: /* =================================================================== */
! 2290: /* A utility method to convert a date string and time string to time_t */
! 2291: /* dateStr: yyyy/mm/dd */
! 2292: /* timeStr: hh:mm */
! 2293: time_t
! 2294: convertTime(dateStr,timeStr)char *dateStr; char *timeStr;
! 2295: {
! 2296: struct tm *theTimeData;
! 2297: time_t result;
! 2298: int dateTime[5];
! 2299: int year, month, day, mm, hh;
! 2300:
! 2301: sscanf(dateStr,"%4d/%2d/%2d",&year,&month,&day);
! 2302: dateTime[0] = month;
! 2303: dateTime[1] = day;
! 2304: dateTime[2] = year;
! 2305: sscanf(timeStr,"%2d:%2d",&hh,&mm);
! 2306: dateTime[3] = hh;
! 2307: dateTime[4] = mm;
! 2308: result = time(NULL);
! 2309: theTimeData = localtime(&result);
! 2310: theTimeData->tm_sec = 0;
! 2311: theTimeData->tm_min = dateTime[4];
! 2312: theTimeData->tm_hour = dateTime[3];
! 2313: theTimeData->tm_mday = dateTime[1];
! 2314: theTimeData->tm_mon = dateTime[0]-1;
! 2315: theTimeData->tm_year = dateTime[2]-1900;/* tm_year is years since 1900 */
! 2316: /* these fields are ignored by mktime
! 2317: theTimeData->tm_wday = weekday(year,month,day);
! 2318: theTimeData->tm_yday = julianday(year,month,day);
! 2319: */
! 2320: result = mktime( theTimeData );
! 2321: return (result);
! 2322: }
! 2323:
! 2324: int
! 2325: weekday( year, month, day) int year; int month; int day;
! 2326: {
! 2327: register int dow;
! 2328: #if defined(hpux)
! 2329: int juldays[13];
! 2330: juldays[0]=0;juldays[1]=0;juldays[2]=31;juldays[3]=59;
! 2331: juldays[4]=90;juldays[5]=120;juldays[6]=151;juldays[7]=181;
! 2332: juldays[8]=212;juldays[9]=243;juldays[10]=273;juldays[11]=304;juldays[12]=334;
! 2333: #else
! 2334: int juldays[13] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
! 2335: #endif
! 2336:
! 2337: dow = 7 + year + year/4 - year/100 + year/400 + juldays[month] + day;
! 2338: if( (month < 3) && ( leap_year(year) ) ) dow--;
! 2339: dow %= 7;
! 2340: return (dow);
! 2341: } /* weekday */
! 2342:
! 2343: int
! 2344: julianday( year, month, day)int year;int month;int day;
! 2345: {
! 2346: register int doy;
! 2347: #if defined(hpux)
! 2348: int juldays[13];
! 2349: juldays[0]=0;juldays[1]=0;juldays[2]=31;juldays[3]=59;
! 2350: juldays[4]=90;juldays[5]=120;juldays[6]=151;juldays[7]=181;
! 2351: juldays[8]=212;juldays[9]=243;juldays[10]=273;juldays[11]=304;juldays[12]=334;
! 2352: #else
! 2353: int juldays[13] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
! 2354: #endif
! 2355:
! 2356: doy = juldays[month];
! 2357: if((month > 2) && (leap_year(year)) ) doy++;
! 2358: doy += day;
! 2359: return (doy);
! 2360: } /* julianday */
! 2361:
! 2362: int
! 2363: check_int( an_int ) char *an_int;
! 2364: {
! 2365: int ii, leng;
! 2366: int result=0;
! 2367:
! 2368: if( (an_int[0] == '-') || (an_int[0]== '+') ) an_int++;
! 2369: leng = strlen(an_int);
! 2370: for(ii=0;ii<leng;ii++) {
! 2371: if( !isdigit(an_int[ii]) ) result = 1;
! 2372: }
! 2373: return (result);
! 2374: }
! 2375: /* --------------------------- */
! 2376: /* 0 OK , 1 NOT a real number */
! 2377: int
! 2378: check_real( a_real ) char *a_real;
! 2379: {
! 2380: int ii, leng;
! 2381: int result=0;
! 2382:
! 2383: if( (a_real[0] == '-') || (a_real[0]== '+') ) a_real++;
! 2384: leng = strlen(a_real);
! 2385: for(ii=0;ii<leng;ii++) {
! 2386: if( (!isdigit(a_real[ii])) && (a_real[ii]!='e') && (a_real[ii]!='E') &&
! 2387: (a_real[ii]!='.') && (a_real[ii]!='+') && (a_real[ii]!='-') ) result = 1;
! 2388: }
! 2389: return (result);
! 2390: }
! 2391:
! 2392: int
! 2393: check_input_usymb(u_symb)char *u_symb;
! 2394: {
! 2395: int result=0;
! 2396:
! 2397:
! 2398: return (result);
! 2399: }
! 2400:
! 2401: /* <== This routine determine emperically where to split a character */
! 2402: /* string into two portions, one for numerical answer and the */
! 2403: /* other for units */
! 2404: /* ----------------------------------------------------------------- */
! 2405: /* inputs : buf : answer string */
! 2406: /* outputs: num : the numerical part */
! 2407: /* num_p : the numerical part in string */
! 2408: /* unit_p : the unit string */
! 2409: /* num_p is used to calculate sig figs */
! 2410: /* return : 0 empty string */
! 2411: /* 1 number without units */
! 2412: /* 2 empty number with units */
! 2413: /* 3 number with units */
! 2414: /* */
! 2415: int split_num_unit(buf,num,num_p,unit_p)
! 2416: char *buf;double *num; char *num_p; char *unit_p;
! 2417: {
! 2418: char num_str[ANSWER_STRING_LENG], unit_str[ANSWER_STRING_LENG];
! 2419: char base_str[ANSWER_STRING_LENG], exp_str[ANSWER_STRING_LENG];
! 2420: int idx=0, errcode=0;
! 2421: int len, ii, n_idx=0, b_idx=0, e_idx=0, u_idx=0;
! 2422: double n_part, x_part, b_part, e_part, result;
! 2423:
! 2424: unit_str[0]=0; /* initialize unit_str[] */
! 2425: len = strlen(buf);
! 2426: while( isspace(buf[idx]) ) { idx++; } /* ignore white spaces */
! 2427: num_str[n_idx]=0; /* initialize number string */
! 2428: if( buf[idx] == '+' || buf[idx] == '-' ) {
! 2429: /* the first char is either '+' or '-' */
! 2430: num_str[n_idx++]= buf[idx++];
! 2431: }
! 2432: /* skip over alphabet char and those that are not '.' */
! 2433: while( (!isdigit( buf[idx] )) && buf[idx] != '.' ) { idx++; }
! 2434: while( isdigit( buf[idx] ) || buf[idx] == '.' ) { /* collect decimal numbers */
! 2435: num_str[n_idx++]= buf[idx++];
! 2436: }
! 2437: num_str[n_idx] = 0; /* end the string with a '\0' */
! 2438: sprintf(num_p,"%s",num_str); /* put the collected numerical string in num_p */
! 2439: /* skip over white spaces */
! 2440: while( isspace(buf[idx]) ) { idx++; }
! 2441: if( buf[idx] == 'e' || buf[idx] == 'E' ) { /* optional e or E part */
! 2442: /* peek further one char to see if it belongs to one of the following */
! 2443: if( buf[idx+1] == '-' || buf[idx+1] == '+' || isspace(buf[idx+1]) || isdigit(buf[idx+1])) {
! 2444: num_str[n_idx++] = buf[idx++]; /* should be 'e' or 'E' */
! 2445: while( isspace(buf[idx]) ) { idx++; } /* skip over spaces */
! 2446: num_str[n_idx++] = buf[idx++]; /* the second char '-', '+' or digit */
! 2447: while( isdigit(buf[idx]) ) { /* only integer is allowed, not '.' */
! 2448: num_str[n_idx++] = buf[idx++];
! 2449: }
! 2450: }
! 2451: num_str[n_idx] = 0; /* terminiate the numerical string */
! 2452: while( isspace(buf[idx]) ) { idx++; }
! 2453: sscanf(num_str, "%lg", &result); /* put the numerical value into a double variable */
! 2454: errcode = errcode | 1;
! 2455: } else if( buf[idx] == 'x' || buf[idx] == 'X') { /* optional x or X part */
! 2456: idx++; /* skip x or X */
! 2457: while( isspace(buf[idx]) ) { idx++; }
! 2458:
! 2459: e_part = 1.0; /* default power */
! 2460: base_str[b_idx] = 0; /* initialize base_str[] */
! 2461: while( isdigit(buf[idx]) || buf[idx] == '.' ) { /* should start with a digit or . */
! 2462: base_str[b_idx++] = buf[idx++];
! 2463: }
! 2464: base_str[b_idx] = 0; /* terminate base_str[] */
! 2465: while( isspace(buf[idx]) ) { idx++; } /* skip over white spaces */
! 2466: if( buf[idx] == '^' ) { /* power */
! 2467: idx++;
! 2468: exp_str[e_idx] = 0; /* initialize exp_str[] */
! 2469: while( isspace(buf[idx]) ) { idx++; }
! 2470: if( buf[idx] == '{'|| buf[idx] == '(' ) { /* matching right bracket */
! 2471: idx++;
! 2472: }
! 2473: while( isspace(buf[idx]) ) { idx++; }
! 2474: if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' ) {
! 2475: exp_str[e_idx] = 0; /* initialize exp_str[], again */
! 2476: while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {
! 2477: exp_str[e_idx++] = buf[idx++];
! 2478: }
! 2479: exp_str[e_idx] = 0; /* terminate exp_str[] */
! 2480: }
! 2481: while( isspace(buf[idx]) ) { idx++; }
! 2482: if( buf[idx] == '}' || buf[idx] == ')' ) {
! 2483: idx++;
! 2484: }
! 2485: sscanf(exp_str, "%lg", &e_part);
! 2486: }
! 2487: if( strlen(base_str) > 0 ) {
! 2488: sscanf(base_str, "%lg", &b_part);
! 2489: x_part = pow(b_part, e_part);
! 2490: } else {
! 2491: x_part = 0.0;
! 2492: }
! 2493: if( strlen(num_str) > 0 ) {
! 2494: sscanf(num_str, "%lg", &n_part);
! 2495: } else {
! 2496: n_part=0.0;
! 2497: }
! 2498: result = n_part * x_part;
! 2499: errcode = errcode | 1;
! 2500: } else if ( buf[idx] == '^' ) { /* number ^ */
! 2501: idx++;
! 2502: e_part = 1.0;
! 2503: while( isspace(buf[idx]) ) { idx++; }
! 2504: if( buf[idx] == '{'|| buf[idx] == '(' ) { /* matching right bracket */
! 2505: idx++;
! 2506: }
! 2507: while( isspace(buf[idx]) ) { idx++; }
! 2508: if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' ) {
! 2509: exp_str[e_idx] = 0;
! 2510: while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {
! 2511: exp_str[e_idx++] = buf[idx++];
! 2512: }
! 2513: exp_str[e_idx] = 0;
! 2514: }
! 2515: while( isspace(buf[idx]) ) { idx++; }
! 2516: if( buf[idx] == '}' || buf[idx] == ')' ) {
! 2517: idx++;
! 2518: }
! 2519: sscanf(exp_str, "%lg", &e_part);
! 2520: sscanf(num_str, "%lg", &n_part);
! 2521: result = pow(n_part,e_part);
! 2522: errcode = errcode | 1;
! 2523: } else { /* number unit */
! 2524: if( strlen(num_str) > 0 ) {
! 2525: sscanf(num_str, "%lg", &result);
! 2526: errcode = errcode | 1;
! 2527: }
! 2528: }
! 2529:
! 2530: if( idx < len ) { /* collect the rest as unit string */
! 2531: for(ii=idx;ii< len; ii++ ) {
! 2532:
! 2533: unit_str[u_idx++] = buf[ii];
! 2534: }
! 2535: unit_str[u_idx]=0; /* terminate unit_str[] */
! 2536: if(u_idx>0) {
! 2537: errcode = errcode | 2;
! 2538: }
! 2539: }
! 2540: if( strlen(num_str) > 0 ) {
! 2541: *num = result;
! 2542: } else { /* empty number string */
! 2543: *num = 0.0;
! 2544: }
! 2545: sprintf(unit_p,"%s", unit_str);
! 2546: return (errcode);
! 2547: }
! 2548:
! 2549: char *
! 2550: answers_string(mode, p)int mode;Problem_t *p;
! 2551: {
! 2552: char *fmted_ans, lower[ANSWER_STRING_LENG], upper[ANSWER_STRING_LENG];
! 2553: char *str_aa, *str_bb, *str_cc, *ans_str, *sub_ans_str, *tmp_str;
! 2554: int len_aa=0, len_bb=0, len_cc=0,len_dd=0, total_len, num_answer;
! 2555: double d_answer;
! 2556:
! 2557: if( p->ans_type == ANSWER_IS_SUBJECTIVE ) {
! 2558: char *a="Subjective Answer\n";
! 2559: ans_str = (char *)capa_malloc(strlen(a)+1,1);
! 2560: strcpy(ans_str,a);
! 2561: return (ans_str);
! 2562: }
! 2563: num_answer = calc_ansrange(p->ans_type,p->calc, p->answer, p->ans_fmt, p->tol_type,
! 2564: p->tolerance, lower, upper);
! 2565:
! 2566: if( p->ans_type == ANSWER_IS_FLOAT ) {
! 2567: fmted_ans = capa_malloc(SMALL_LINE_BUFFER,1);
! 2568: d_answer = (double)atof(p->answer);
! 2569: sprintf(fmted_ans,p->ans_fmt,d_answer);
! 2570: } else {
! 2571: fmted_ans = capa_malloc(strlen(p->answer)+2,1);
! 2572: strcpy(fmted_ans,p->answer);
! 2573: }
! 2574:
! 2575: len_aa = strlen(fmted_ans);
! 2576: if (lower != NULL ) len_bb = strlen(lower); else len_bb = 0;
! 2577: if (upper != NULL ) len_cc = strlen(upper); else len_cc = 0;
! 2578: if ( p->unit_str != NULL ) len_dd = strlen(p->unit_str); else len_dd = 0;
! 2579:
! 2580: switch(mode) {
! 2581: case TeX_MODE:
! 2582: if(num_answer==2) {
! 2583: /* 16 is by adding up characters ' [,] \n\n' and others */
! 2584: str_aa = format_toTeX(fmted_ans);
! 2585: total_len = strlen(str_aa) + len_dd + 16;
! 2586: str_bb = format_toTeX(lower);
! 2587: total_len += strlen(str_bb);
! 2588: str_cc = format_toTeX(upper);
! 2589: total_len += strlen(str_cc);
! 2590: ans_str = (char *)capa_malloc(total_len,1);
! 2591: if(len_dd == 0 ) { /* no unit_str */
! 2592: sprintf(ans_str," %s [%s,%s]\n\n", str_aa,str_bb,str_cc);
! 2593: } else {
! 2594: sprintf(ans_str," %s [%s,%s] $%s$\n\n", str_aa,str_bb,str_cc,p->unit_str);
! 2595: }
! 2596: capa_mfree((char *)str_aa);
! 2597: capa_mfree((char *)str_bb);
! 2598: capa_mfree((char *)str_cc);
! 2599: } else { /* only one answer */
! 2600: if ( (p->ans_type == ANSWER_IS_INTEGER) ||
! 2601: (p->ans_type == ANSWER_IS_FLOAT )) {
! 2602: str_bb = format_toTeX(lower);
! 2603: } else { /* answer could be string, choice */
! 2604: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
! 2605: if (p->ans_type == ANSWER_IS_FORMULA || 1)
! 2606: sprintf(str_bb,"\\begin{verbatim}%s\\end{verbatim}",lower);
! 2607: else
! 2608: strcpy(str_bb,lower);
! 2609: }
! 2610: total_len = strlen(str_bb) + len_dd + 8;
! 2611: /* 4 is by adding up characters ' \\\n' plus four */
! 2612: ans_str = (char *)capa_malloc(sizeof(char),total_len);
! 2613: if(len_dd == 0 ) { /* no unit_str */
! 2614: sprintf(ans_str," %s\n", str_bb);
! 2615: } else {
! 2616: sprintf(ans_str," %s $%s$\n", str_bb,p->unit_str);
! 2617: }
! 2618: capa_mfree((char *)str_bb);
! 2619: }
! 2620: break;
! 2621: case ASCII_MODE:
! 2622: total_len = len_aa + len_bb + len_cc + len_dd + 8;
! 2623: /* 8 is by adding up characters ' [,] \n\n' plus one */
! 2624: ans_str = (char *)capa_malloc(sizeof(char),total_len);
! 2625: if(num_answer==2) {
! 2626: if(len_dd == 0 ) { /* no unit_str */
! 2627: sprintf(ans_str,"%s [%s,%s]\n\n", fmted_ans,lower,upper);
! 2628: } else {
! 2629: sprintf(ans_str,"%s [%s,%s] %s\n\n", fmted_ans,lower,upper,p->unit_str);
! 2630: }
! 2631: } else {
! 2632: if(len_dd == 0 ) { /* no unit_str */
! 2633: sprintf(ans_str,"%s\n\n", lower);
! 2634: } else {
! 2635: sprintf(ans_str,"%s %s\n\n", lower,p->unit_str);
! 2636: }
! 2637: }
! 2638: break;
! 2639: case ANSWER_STRING_MODE:
! 2640: total_len = len_aa + len_bb + len_cc + len_dd + 8;
! 2641: /* 8 is by adding up characters ' [,] \n\n' plus one */
! 2642: ans_str = (char *)capa_malloc(sizeof(char),total_len);
! 2643: if(num_answer==2) {
! 2644: if(len_dd == 0 ) { /* no unit_str */
! 2645: sprintf(ans_str,"%s", fmted_ans);
! 2646: } else {
! 2647: sprintf(ans_str,"%s %s", fmted_ans,p->unit_str);
! 2648: }
! 2649: } else {
! 2650: if(len_dd == 0 ) { /* no unit_str */
! 2651: sprintf(ans_str,"%s", lower);
! 2652: } else {
! 2653: sprintf(ans_str,"%s %s", lower,p->unit_str);
! 2654: }
! 2655: }
! 2656: break;
! 2657: case HTML_MODE:
! 2658: if(num_answer==2) { /* this indicates that answer should be either float or int
! 2659: */
! 2660: str_aa = format_toHTML(fmted_ans);
! 2661: total_len = strlen(str_aa) + len_dd + 8;
! 2662: str_bb = format_toHTML(lower);
! 2663: total_len += strlen(str_bb);
! 2664: str_cc = format_toHTML(upper);
! 2665: total_len += strlen(str_cc);
! 2666: /* 8 is by adding up characters ' [,] \n\n' plus one */
! 2667: ans_str = (char *)capa_malloc(sizeof(char),total_len);
! 2668: if(len_dd == 0 ) { /* no unit_str */
! 2669: sprintf(ans_str,"%s [%s,%s]\n\n", str_aa,str_bb,str_cc);
! 2670: } else {
! 2671: sprintf(ans_str,"%s [%s,%s] %s\n\n", str_aa,str_bb,str_cc,p->unit_str);
! 2672: }
! 2673: capa_mfree((char *)str_aa); capa_mfree((char *)str_bb); capa_mfree((char
! 2674: *)str_cc);
! 2675: } else {
! 2676: if ( (p->ans_type == ANSWER_IS_INTEGER) ||
! 2677: (p->ans_type == ANSWER_IS_FLOAT )) {
! 2678: str_bb = format_toHTML(lower);
! 2679: } else { /* answer could be string, choice */
! 2680: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
! 2681: if (p->ans_type == ANSWER_IS_FORMULA || 1)
! 2682: sprintf(str_bb,"<PRE>\n%s\n</PRE>",lower);
! 2683: else
! 2684: strcpy(str_bb,lower);
! 2685: }
! 2686: total_len = strlen(str_bb) + len_dd + 4;
! 2687: /* 4 is by adding up characters ' \n\n' plus one */
! 2688: ans_str = (char *)capa_malloc(sizeof(char),total_len);
! 2689: if(len_dd == 0 ) { /* no unit_str */
! 2690: sprintf(ans_str,"%s\n\n", str_bb);
! 2691: } else {
! 2692: sprintf(ans_str,"%s %s\n\n", str_bb,p->unit_str);
! 2693: }
! 2694: capa_mfree((char *)str_bb);
! 2695: }
! 2696: break;
! 2697: }
! 2698: capa_mfree(fmted_ans);
! 2699:
! 2700: if( p->ans_cnt > 1 ) {
! 2701: AnswerInfo_t *ai;
! 2702: for( ai = p->ans_list; ai; ai = ai->ans_next) {
! 2703: num_answer = calc_ansrange(ai->ans_type,ai->ans_calc, ai->ans_str, ai->ans_fmt,
! 2704: ai->ans_tol_type,ai->ans_tol,lower,upper);
! 2705: if( ai->ans_type == ANSWER_IS_FLOAT ) {
! 2706: fmted_ans = capa_malloc(SMALL_LINE_BUFFER,1);
! 2707: d_answer = (double)atof(ai->ans_str);
! 2708: sprintf(fmted_ans,ai->ans_fmt,d_answer);
! 2709: } else {
! 2710: fmted_ans = capa_malloc(strlen(ai->ans_str)+2,1);
! 2711: strcpy(fmted_ans,ai->ans_str);
! 2712: }
! 2713: len_aa = strlen(fmted_ans);
! 2714: len_bb = strlen(lower);
! 2715: len_cc = strlen(upper);
! 2716: len_dd = strlen(ai->ans_unit_str);
! 2717: switch(mode) {
! 2718: case TeX_MODE:
! 2719: if(num_answer==2) {
! 2720: /* 16 is by adding up characters ' [,] \n\n' and others */
! 2721:
! 2722: str_aa = format_toTeX(fmted_ans);
! 2723: total_len = strlen(str_aa) + len_dd + 16;
! 2724: str_bb = format_toTeX(lower);
! 2725: total_len += strlen(str_bb);
! 2726: str_cc = format_toTeX(upper);
! 2727: total_len += strlen(str_cc);
! 2728:
! 2729: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
! 2730:
! 2731: if(len_dd == 0 ) { /* no unit_str */
! 2732: sprintf(sub_ans_str," %s [%s,%s]\n\n", str_aa,str_bb,str_cc);
! 2733: } else {
! 2734: sprintf(sub_ans_str," %s [%s,%s] $%s$\n\n",
! 2735: str_aa,str_bb,str_cc,ai->ans_unit_str);
! 2736: }
! 2737: capa_mfree((char *)str_aa); capa_mfree((char *)str_bb); capa_mfree((char *)str_cc);
! 2738: } else { /* only one answer */
! 2739: if ( (ai->ans_type == ANSWER_IS_INTEGER) ||
! 2740: (ai->ans_type == ANSWER_IS_FLOAT )) {
! 2741: str_bb = format_toTeX(lower);
! 2742: } else { /* answer could be string, choice */
! 2743: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
! 2744: if (ai->ans_type == ANSWER_IS_FORMULA || 1)
! 2745: sprintf(str_bb,"\\begin{verbatim}%s\\end{verbatim}",lower);
! 2746: else
! 2747: strcpy(str_bb,lower);
! 2748: }
! 2749: total_len = strlen(str_bb) + len_dd + 8;
! 2750: /* 4 is by adding up characters ' \\\n' plus four */
! 2751: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
! 2752: if(len_dd == 0 ) { /* no unit_str */
! 2753: sprintf(sub_ans_str," %s\n", str_bb);
! 2754: } else {
! 2755: sprintf(sub_ans_str," %s $%s$\n", str_bb,ai->ans_unit_str);
! 2756: }
! 2757: capa_mfree((char *)str_bb);
! 2758: }
! 2759: break;
! 2760: case ASCII_MODE:
! 2761: total_len = len_aa + len_bb + len_cc + len_dd + 8;
! 2762: /* 8 is by adding up characters ' [,] \n\n' plus one */
! 2763: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
! 2764: if(num_answer==2) {
! 2765: if(len_dd == 0 ) { /* no unit_str */
! 2766: sprintf(sub_ans_str,"%s [%s,%s]\n\n", fmted_ans,lower,upper);
! 2767: } else {
! 2768: sprintf(sub_ans_str,"%s [%s,%s] %s\n\n",
! 2769: fmted_ans,lower,upper,ai->ans_unit_str);
! 2770: }
! 2771: } else {
! 2772: if(len_dd == 0 ) { /* no unit_str */
! 2773: sprintf(sub_ans_str,"%s\n\n", lower);
! 2774: } else {
! 2775: sprintf(sub_ans_str,"%s %s\n\n", lower,ai->ans_unit_str);
! 2776: }
! 2777: }
! 2778: break;
! 2779: case ANSWER_STRING_MODE:
! 2780: total_len = len_aa + len_bb + len_cc + len_dd + 8;
! 2781: /* 8 is by adding up characters ' [,] \n\n' plus one */
! 2782: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
! 2783: if(num_answer==2) {
! 2784: if(len_dd == 0 ) { /* no unit_str */
! 2785: sprintf(sub_ans_str,", %s", fmted_ans);
! 2786: } else {
! 2787: sprintf(sub_ans_str,", %s %s", fmted_ans,ai->ans_unit_str);
! 2788: }
! 2789: } else {
! 2790: if(len_dd == 0 ) { /* no unit_str */
! 2791: sprintf(sub_ans_str,", %s", lower);
! 2792: } else {
! 2793: sprintf(sub_ans_str,", %s %s", lower,ai->ans_unit_str);
! 2794: }
! 2795: }
! 2796: break;
! 2797: case HTML_MODE:
! 2798: if(num_answer==2) {
! 2799: str_aa = format_toHTML(fmted_ans);
! 2800: total_len = strlen(str_aa) + len_dd + 8;
! 2801: str_bb = format_toHTML(lower);
! 2802: total_len += strlen(str_bb);
! 2803: str_cc = format_toHTML(upper);
! 2804: total_len += strlen(str_cc);
! 2805: /* 8 is by adding up characters ' [,] \n\n' plus one */
! 2806: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
! 2807: if(len_dd == 0 ) { /* no unit_str */
! 2808: sprintf(sub_ans_str,"%s [%s,%s]\n\n", str_aa,str_bb,str_cc);
! 2809: } else {
! 2810: sprintf(sub_ans_str,"%s [%s,%s] %s\n\n",
! 2811: str_aa,str_bb,str_cc,ai->ans_unit_str);
! 2812: }
! 2813: capa_mfree((char *)str_aa); capa_mfree((char *)str_bb); capa_mfree((char
! 2814: *)str_cc);
! 2815: } else {
! 2816: if ( (ai->ans_type == ANSWER_IS_INTEGER) ||
! 2817: (ai->ans_type == ANSWER_IS_FLOAT )) {
! 2818: str_bb = format_toHTML(lower);
! 2819: } else { /* answer could be string, choice */
! 2820: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
! 2821: if (ai->ans_type == ANSWER_IS_FORMULA || 1)
! 2822: sprintf(str_bb,"<PRE>\n%s\n</PRE>",lower);
! 2823: else
! 2824: strcpy(str_bb,lower);
! 2825: }
! 2826: total_len = strlen(str_bb) + len_dd + 4;
! 2827: /* 4 is by adding up characters ' \n\n' plus one */
! 2828: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
! 2829: if(len_dd == 0 ) { /* no unit_str */
! 2830: sprintf(sub_ans_str,"%s\n\n", str_bb);
! 2831: } else {
! 2832: sprintf(sub_ans_str,"%s %s\n\n", str_bb,ai->ans_unit_str);
! 2833: }
! 2834: capa_mfree((char *)str_bb);
! 2835: }
! 2836: break;
! 2837: } /* end of switch */
! 2838: total_len = strlen(ans_str);
! 2839: total_len += (strlen(sub_ans_str) + 1);
! 2840: tmp_str = (char *)capa_malloc(sizeof(char),total_len);
! 2841: strncpy(tmp_str, ans_str, strlen(ans_str)+1);
! 2842: strcat(tmp_str, sub_ans_str);
! 2843: capa_mfree(ans_str); capa_mfree(sub_ans_str);
! 2844: capa_mfree(fmted_ans);
! 2845: ans_str = tmp_str;
! 2846: } /* end of for */
! 2847: } /* end of if */
! 2848:
! 2849: return (ans_str); /* the calling routing needs to deallocate it */
! 2850: }
! 2851:
! 2852:
! 2853:
! 2854: /* ------------------------------ called from capalogin */
! 2855: /* impose stronger checking on the user input string *answer */
! 2856: /* */
! 2857:
! 2858: /* <== This routine checks user input string *ans against correct answer *s ==> */
! 2859: int
! 2860: capa_check_ans(ai,ans) AnswerInfo_t *ai; char *ans;
! 2861: {
! 2862: int t; /* ans_type */
! 2863: char *s; /* ans_str */
! 2864: int c; /* ans_calc */
! 2865: int tt; /* ans_tol_type */
! 2866: double to; /* ans_tol */
! 2867: int su; /* ans_sig_ub */
! 2868: int sl; /* ans_sig_lb */
! 2869: char *fm; /* ans_fmt */
! 2870: char *us; /* ans_unit_str */
! 2871: Unit_t *u_p; /* ans_unit */
! 2872: int input_len, all_alphabet = 1, idx, ii, type;
! 2873: int outcome, result = INCORRECT;
! 2874: int sig, corr_len;
! 2875: int choice[ANSWER_STRING_LENG];
! 2876: char num_str[ANSWER_STRING_LENG], unit_str[ANSWER_STRING_LENG];
! 2877: char fmted[ANSWER_STRING_LENG], correct[ANSWER_STRING_LENG], answer[ANSWER_STRING_LENG];
! 2878: double n_part;
! 2879: double given, target, ratio, fmted_target, target_u, target_l, scale=1.0;
! 2880: double delta;
! 2881:
! 2882: t = ai->ans_type; s = ai->ans_str; c = ai->ans_calc;
! 2883: tt = ai->ans_tol_type; to = ai->ans_tol;
! 2884: su = ai->ans_sig_ub; sl = ai->ans_sig_lb;
! 2885: fm = ai->ans_fmt;
! 2886: us = ai->ans_unit_str; u_p = ai->ans_unit;
! 2887:
! 2888: switch(t) {
! 2889: case ANSWER_IS_INTEGER:
! 2890: case ANSWER_IS_FLOAT:
! 2891: {
! 2892: input_len = strlen(ans);
! 2893: all_alphabet = 1;
! 2894: for(idx=0;idx<input_len;idx++) {
! 2895: if( isdigit(ans[idx]) ) {
! 2896: all_alphabet = 0;
! 2897: }
! 2898: }
! 2899: if( !all_alphabet ) { /* answer string is not all alphabets */
! 2900: outcome = split_num_unit(ans,&n_part,num_str,unit_str);
! 2901: if( outcome > 1 ) { /* with both num and unit parts or only unit part */
! 2902: if( u_p != NULL ) {
! 2903: result = check_correct_unit(unit_str,u_p,&scale);
! 2904: } else { /* what to do when no unit is specified but student entered a unit? */
! 2905: result = UNIT_NOTNEEDED;
! 2906: }
! 2907: } else {
! 2908: if( u_p != NULL ) {
! 2909: result = NO_UNIT;
! 2910: }
! 2911: }
! 2912: if( (result != NO_UNIT) && (result != UNIT_FAIL) && ( result != UNIT_NOTNEEDED) ) {
! 2913: if( t == ANSWER_IS_FLOAT ) {
! 2914: target = (double)atof(s); /* real number */
! 2915: } else {
! 2916: target = (double)atol(s); /* Integer answer */
! 2917: }
! 2918: given = n_part * scale; /* convert the given answer into proper scale for units */
! 2919: sig = calc_sig( num_str );
! 2920: if( (sig < sl) || (sig > su) ) {
! 2921: result = SIG_FAIL;
! 2922: } else {
! 2923: switch( tt ) { /* tolerence type */
! 2924: case TOL_ABSOLUTE:
! 2925: fmted_target = target; /* if answer type is integer */
! 2926: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
! 2927: sprintf(fmted, fm, target);
! 2928: fmted_target = (double)atof(fmted);
! 2929: }
! 2930: to = fabs(to); /* tol must be positive */
! 2931: if( c == CALC_FORMATED) {
! 2932: target_l = fmted_target - to; target_u = fmted_target + to;
! 2933: } else {
! 2934: target_l = target - to; target_u = target + to;
! 2935: }
! 2936: if( (given >= target_l) && (given <= target_u) ) {
! 2937: result = APPROX_ANS;
! 2938: } else { result = INCORRECT; }
! 2939: break;
! 2940: case TOL_PERCENTAGE:
! 2941: if( target != 0.0 ) {
! 2942: ratio = (double)(to / 100.0);
! 2943: fmted_target = target; /* if answer type is integer */
! 2944: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
! 2945: sprintf(fmted, fm, target);
! 2946: fmted_target = (double)atof(fmted);
! 2947: }
! 2948: delta = (double)fabs((double)ratio*target);
! 2949: if( c == CALC_FORMATED) {
! 2950: target_l = fmted_target - delta; target_u = fmted_target + delta;
! 2951: } else {
! 2952: target_l = target - delta; target_u = target + delta;
! 2953: }
! 2954: } else { target_l = target_u = target; }
! 2955: if ( (given >= target_l) && (given <= target_u) ) {
! 2956: result = APPROX_ANS;
! 2957: } else { result = INCORRECT; }
! 2958: break;
! 2959: }
! 2960: } /* end sig check */
! 2961: } /* end if unit check */
! 2962: } else { /* user entered alphabets, but no number */
! 2963: result = INCORRECT;
! 2964: }
! 2965: }
! 2966: break;
! 2967: case ANSWER_IS_CHOICE:
! 2968: {
! 2969: corr_len = strlen(s); input_len = strlen(ans);
! 2970: if( corr_len == input_len ) {
! 2971: for(idx=0;idx<ANSWER_STRING_LENG;idx++) choice[idx] = 0;
! 2972: result = EXACT_ANS;
! 2973: for(ii=0;ii<corr_len; ii++) {
! 2974: idx = toupper(correct[ii]) - 'A'; choice[idx] = 1;
! 2975: }
! 2976: for(ii=0;ii<input_len;ii++) {
! 2977: idx = toupper(answer[ii]) - 'A';
! 2978: if(choice[idx] != 1 ) result = INCORRECT;
! 2979: }
! 2980: } else { result = INCORRECT; }
! 2981: break;
! 2982: }
! 2983: case ANSWER_IS_STRING_CI:
! 2984: if (strcasecmp(ans, s)) { result = INCORRECT; } else { result = EXACT_ANS; }
! 2985: break;
! 2986: case ANSWER_IS_STRING_CS:
! 2987: if (strcmp(ans, s)) { result = INCORRECT; } else { result = EXACT_ANS; }
! 2988: break;
! 2989: case ANSWER_IS_FORMULA:
! 2990: result = check_formula_ans(s,ans,ai->ans_id_list,ai->ans_pts_list,tt,to);
! 2991: break;
! 2992: case ANSWER_IS_EXTERNAL: /* Not yet implemented */
! 2993: break;
! 2994: }
! 2995: return (result);
! 2996: }
! 2997:
! 2998: /* =============================================================================== */
! 2999: /* calling sequence capa_check_answers() --> capa_check_answer() */
! 3000: /* --> capa_check_ans() */
! 3001:
! 3002:
! 3003: /* How we check the correct answer against user input string */
! 3004: /*
! 3005: If the correct answer is a number (either integer or real number)
! 3006: check if user input string consists of only alphabet characters
! 3007: use split_num_unit() heuristic function to split the input string into two parts
! 3008: numerical part and units part.
! 3009: if the outcome contains units, check if the units is correct or not
! 3010:
! 3011: */
! 3012:
! 3013:
! 3014: int
! 3015: capa_check_answer(p, answer) Problem_t *p; char *answer;
! 3016: {
! 3017: int type;
! 3018: char *correct;
! 3019: char input[ANSWER_STRING_LENG], unit_str[ANSWER_STRING_LENG];
! 3020: int tol_type, calc_type;
! 3021: double tol, n_part;
! 3022: int sig_l;
! 3023: int sig_u;
! 3024: char *fmt;
! 3025: int choice[ANSWER_STRING_LENG], ii, idx, corr_len, input_len;
! 3026: int result = INCORRECT, sig, outcome, all_alphabet;
! 3027: char fmted[FORMAT_STRING_LENG];
! 3028: double given, target, ratio, fmted_target, target_u, target_l, scale=1.0;
! 3029: double delta;
! 3030:
! 3031: type = p->ans_type;
! 3032: correct = p->answer;
! 3033: tol_type = p->tol_type;
! 3034: tol = p->tolerance;
! 3035: sig_l = p->sig_lbound;
! 3036: sig_u = p->sig_ubound;
! 3037: fmt = p->ans_fmt;
! 3038: calc_type = p->calc;
! 3039: unit_str[0]=0;
! 3040:
! 3041: switch(type) {
! 3042: case ANSWER_IS_INTEGER:
! 3043: case ANSWER_IS_FLOAT:
! 3044: {
! 3045: input_len = strlen(answer);
! 3046: all_alphabet = 1;
! 3047: for(idx=0;idx<input_len;idx++) {
! 3048: if( isdigit(answer[idx]) ) {
! 3049: all_alphabet = 0;
! 3050: }
! 3051: }
! 3052: if( !all_alphabet ) {
! 3053: outcome = split_num_unit(answer,&n_part,input,unit_str);
! 3054: if( outcome > 1 ) { /* with both num and unit parts or only unit part */
! 3055: if( p->ans_unit != NULL ) {
! 3056: result = check_correct_unit(unit_str,p->ans_unit,&scale);
! 3057:
! 3058: } else { /* what to do when no unit is specified but student entered a unit? */
! 3059: result = UNIT_NOTNEEDED;
! 3060: }
! 3061: } else {
! 3062: if( p->ans_unit != NULL ) {
! 3063: result = NO_UNIT;
! 3064: }
! 3065: }
! 3066: if( (result != NO_UNIT) && (result != UNIT_FAIL) && ( result != UNIT_NOTNEEDED) ) {
! 3067: if( type == ANSWER_IS_FLOAT ) {
! 3068: target = (double)atof(correct); /* real number */
! 3069: } else {
! 3070: target = (double)atol(correct); /* Integer answer */
! 3071: }
! 3072: given = n_part * scale; /* convert the given answer into proper scale for units */
! 3073: sig = calc_sig( input );
! 3074: if( (sig < sig_l) || (sig > sig_u) ) {
! 3075: result = SIG_FAIL;
! 3076: } else {
! 3077: switch( tol_type ) {
! 3078: case TOL_ABSOLUTE:
! 3079: fmted_target = target; /* if answer type is integer */
! 3080: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
! 3081: sprintf(fmted, fmt, target);
! 3082: fmted_target = (double)atof(fmted);
! 3083: }
! 3084: tol = fabs(tol); /* tol must be positive */
! 3085: if( calc_type == CALC_FORMATED) {
! 3086: target_l = fmted_target - tol; target_u = fmted_target + tol;
! 3087: } else {
! 3088: target_l = target - tol; target_u = target + tol;
! 3089: }
! 3090: if( (given >= target_l) && (given <= target_u) ) {
! 3091: result = APPROX_ANS;
! 3092: } else { result = INCORRECT; }
! 3093: break;
! 3094: case TOL_PERCENTAGE:
! 3095: if( target != 0.0 ) {
! 3096: ratio = (double)(tol / 100.0);
! 3097: fmted_target = target; /* if answer type is integer */
! 3098: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
! 3099: sprintf(fmted, fmt, target);
! 3100: fmted_target = (double)atof(fmted);
! 3101: }
! 3102: delta = (double)fabs((double)ratio*target);
! 3103: if( calc_type == CALC_FORMATED) {
! 3104: target_l = fmted_target - delta; target_u = fmted_target + delta;
! 3105: } else {
! 3106: target_l = target - delta; target_u = target + delta;
! 3107: }
! 3108: } else { target_l = target_u = target; }
! 3109: if ( (given >= target_l) && (given <= target_u) ) {
! 3110: result = APPROX_ANS;
! 3111: } else { result = INCORRECT; }
! 3112: break;
! 3113: }
! 3114: } /* end sig check */
! 3115: } /* end if unit check */
! 3116: } else { /* user entered alphabet, but no number */
! 3117: result = INCORRECT;
! 3118: }
! 3119: }
! 3120: break;
! 3121: case ANSWER_IS_CHOICE:
! 3122: {
! 3123: corr_len = strlen(correct); input_len = strlen(answer);
! 3124: if( corr_len == input_len ) {
! 3125: for(ii=0;ii<ANSWER_STRING_LENG;ii++) choice[ii] = 0; result = EXACT_ANS;
! 3126: for(ii=0;ii<corr_len; ii++) {
! 3127: idx = toupper(correct[ii]) - 'A'; choice[idx] = 1;
! 3128: }
! 3129: for(ii=0;ii<input_len;ii++) {
! 3130: idx = toupper(answer[ii]) - 'A';
! 3131: if(choice[idx] != 1 ) result = INCORRECT;
! 3132: }
! 3133: } else { result = INCORRECT; }
! 3134: break;
! 3135: }
! 3136: case ANSWER_IS_STRING_CI:
! 3137: if (strcasecmp(answer, correct)) { result = INCORRECT; } else { result = EXACT_ANS; }
! 3138: break;
! 3139: case ANSWER_IS_STRING_CS:
! 3140: if (strcmp(answer, correct)) { result = INCORRECT; } else { result = EXACT_ANS; }
! 3141: break;
! 3142: case ANSWER_IS_FORMULA:
! 3143: result = check_formula_ans(correct,answer,p->id_list,p->pts_list,tol_type,tol);
! 3144: break;
! 3145: case ANSWER_IS_EXTERNAL: /* not yet implemented */
! 3146: break;
! 3147:
! 3148: }
! 3149: return (result);
! 3150: }
! 3151:
! 3152: /* ----------------------------------------------------------------------------------- */
! 3153: /* assumming the formula is *fml_str and the student input is *input_str */
! 3154: /* according to the type of tolerance, we form the final formula as */
! 3155: /* absolute tolerance: (*fml_str) - (*input_str) */
! 3156: /* relative tolerance: (*input_str) / (*fml_str) */
! 3157: int
! 3158: check_formula_ans(fml_str,input_str,var_list,pts_list,tol_type,tol)
! 3159: char *fml_str;char *input_str;char *var_list;PointsList_t *pts_list;int tol_type; double tol;
! 3160: {
! 3161: char *check_fml_str;
! 3162: int f_len, i_len, outcome, error_code;
! 3163: PointsList_t *pt, *next;
! 3164: double formula_val, diff;
! 3165:
! 3166: f_len = strlen(fml_str);
! 3167: i_len = strlen(input_str);
! 3168:
! 3169: check_fml_str = (char *)capa_malloc((f_len + i_len + 16), sizeof(char));
! 3170: if( tol_type == TOL_ABSOLUTE ) {
! 3171: sprintf(check_fml_str,"abs((%s) - (%s))",fml_str, input_str);
! 3172: } else {
! 3173: sprintf(check_fml_str,"(%s) / (%s)",input_str,fml_str);
! 3174: }
! 3175: outcome = APPROX_ANS;
! 3176: for(pt= pts_list; pt!=NULL ; pt=next) {
! 3177: next=pt->pts_next;
! 3178: error_code = f_eval_formula(&formula_val,check_fml_str, var_list, pt->pts_str);
! 3179: if( ! error_code ) {
! 3180: if( tol_type == TOL_ABSOLUTE ) {
! 3181: diff = tol - formula_val;
! 3182: if( diff < 0.0 ) {
! 3183: outcome = INCORRECT;
! 3184: }
! 3185: } else {
! 3186: diff = abs(1.0 - formula_val) * 100.0 ;
! 3187: if( diff < tol ) {
! 3188: outcome = INCORRECT;
! 3189: }
! 3190: }
! 3191: } else {
! 3192: outcome = BAD_FORMULA;
! 3193: break;
! 3194: }
! 3195: }
! 3196: capa_mfree((char *)check_fml_str);
! 3197:
! 3198: return (outcome);
! 3199:
! 3200: }
! 3201: /* inputs: type :: answer type, calc_type :: input string format string tolerance type */
! 3202: /* returns: lower upper */
! 3203:
! 3204: int
! 3205: calc_ansrange(type, calc_type, input, fmt, tol_type, tol, lower, upper)
! 3206: int type;int calc_type;char *input;char *fmt;
! 3207: int tol_type;double tol;char *lower;char *upper;
! 3208: {
! 3209: int result = 2, leng;
! 3210: char fmted[ANSWER_STRING_LENG];
! 3211: double target, fmted_target, ratio, target_l, target_u, tmp, delta;
! 3212:
! 3213:
! 3214: if( (type == ANSWER_IS_FORMULA) ||
! 3215: (type == ANSWER_IS_EXTERNAL ) ) {
! 3216: strcpy(lower, input);
! 3217: result = 1;
! 3218: return (result);
! 3219: } else {
! 3220: if( tol == 0.0 ) { /* answer could be ANSWER_IS_FLOAT ANSWER_IS_INTEGER,
! 3221: ANSWER_IS_STRING_CI ANSWER_IS_STRING_CS
! 3222: ANSWER_IS_CHOICE
! 3223: */
! 3224: result = 1; /* only one answer */
! 3225: if( type == ANSWER_IS_FLOAT ) {
! 3226: target = (double)atof(input);
! 3227: sprintf(fmted, fmt, target);
! 3228: leng = strlen(fmted)+1;
! 3229:
! 3230: strcpy(lower, fmted);
! 3231: } else { /* could be integer, choice, string ci, string cs */
! 3232: strcpy(lower, input);
! 3233: }
! 3234: } else { /* we have tolerence */
! 3235:
! 3236: target = (double)atof(input);
! 3237: switch( tol_type ) {
! 3238: case TOL_ABSOLUTE:
! 3239: fmted_target = target; /* if answer type is integer */
! 3240: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
! 3241: sprintf(fmted, fmt, target);
! 3242: fmted_target = (double)atof(fmted);
! 3243: }
! 3244: tol = fabs(tol); /* tol must be positive */
! 3245: if( calc_type == CALC_FORMATED) {
! 3246: target_l = fmted_target - tol; target_u = fmted_target + tol;
! 3247: } else {
! 3248: target_l = target - tol; target_u = target + tol;
! 3249: }
! 3250: if(type == ANSWER_IS_FLOAT) {
! 3251: sprintf(fmted, fmt, target_l ); strcpy(lower, fmted);
! 3252: sprintf(fmted, fmt, target_u ); strcpy(upper, fmted);
! 3253: } else {
! 3254: sprintf(fmted, "%.15g", target_l ); strcpy(lower, fmted);
! 3255: sprintf(fmted, "%.15g", target_u ); strcpy(upper, fmted);
! 3256: }
! 3257: break;
! 3258: case TOL_PERCENTAGE:
! 3259: if( target != 0.0 ) {
! 3260: ratio = (double)(tol / 100.0);
! 3261: fmted_target = target; /* if answer type is integer */
! 3262: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
! 3263: sprintf(fmted, fmt, target);
! 3264: fmted_target = (double)atof(fmted);
! 3265: }
! 3266: delta = (double)fabs((double)ratio*target);
! 3267: if( calc_type == CALC_FORMATED) {
! 3268: target_l = fmted_target - delta; target_u = fmted_target + delta;
! 3269: } else {
! 3270: target_l = target - delta; target_u = target + delta;
! 3271: }
! 3272: if( target_l > target_u ) { tmp = target_u; target_u = target_l; target_l = tmp; }
! 3273: if(type == ANSWER_IS_FLOAT) {
! 3274: sprintf(fmted, fmt, target_l ); strcpy(lower, fmted);
! 3275: sprintf(fmted, fmt, target_u ); strcpy(upper, fmted);
! 3276: } else {
! 3277: sprintf(fmted, "%.15g", target_l ); strcpy(lower, fmted);
! 3278: sprintf(fmted, "%.15g", target_u ); strcpy(upper, fmted);
! 3279: }
! 3280: } else { strcpy(lower, "0.0"); strcpy(upper, "0.0"); result = 1;}
! 3281: break;
! 3282: }
! 3283: }
! 3284: }
! 3285:
! 3286: return (result);
! 3287: }
! 3288:
! 3289: /* Algorithms : check ALL units first */
! 3290: /* sig figs second */
! 3291: /* numerical, string comparisons last */
! 3292: /* result from capa_check_ans() could be */
! 3293:
! 3294: /* New check answers routine checks the /AND and /OR group of answers */
! 3295: /* use array of char pointers char **a */
! 3296: int
! 3297: capa_check_answers(p,answers,cnt) Problem_t *p; char **answers; int cnt;
! 3298: {
! 3299: AnswerInfo_t *ai;
! 3300: int ii, done, result;
! 3301: int *outcomes;
! 3302:
! 3303: if(p->ans_op == ANS_AND) { /* ans /and ans */
! 3304: if( (cnt != p->ans_cnt) ) { return (ANS_CNT_NOT_MATCH); }
! 3305: if( cnt == 1 ) { return (capa_check_answer(p, answers[0])); } /* there is only one answer */
! 3306: outcomes = (int *)capa_malloc(sizeof(int),cnt);
! 3307: for(ii=0;ii<cnt;ii++) outcomes[ii]=0; /* initialize the outcomes array */
! 3308: outcomes[0] = capa_check_answer(p, answers[0]);
! 3309: for(ii=1, ai = p->ans_list; ai; ii++,ai = ai->ans_next ) {
! 3310: outcomes[ii] = capa_check_ans(ai,answers[ii]);
! 3311: }
! 3312: done = ii = 0;
! 3313: result = 0;
! 3314: while( !done ) { /* check if any of the outcome has failed on units */
! 3315: if( (outcomes[ii] == UNIT_FAIL) ||
! 3316: (outcomes[ii] == NO_UNIT) ||
! 3317: (outcomes[ii] == UNIT_NOTNEEDED) ) {
! 3318: result = outcomes[ii];
! 3319: done = 1;
! 3320: }
! 3321: ii++;
! 3322: if(ii==cnt) done = 1;
! 3323: }
! 3324: if( result == 0 ) { /* check if any of the outcome has failed on sig figs */
! 3325: done = ii = 0;
! 3326: while( !done ) {
! 3327: if( outcomes[ii] == SIG_FAIL ) {
! 3328: result = outcomes[ii];
! 3329: done = 1;
! 3330: }
! 3331: ii++;
! 3332: if(ii==cnt) done = 1;
! 3333: }
! 3334: }
! 3335: if( result == 0 ) { /* check if any of the outcome is incorrect */
! 3336: done = ii = 0;
! 3337: while( !done ) {
! 3338: if( outcomes[ii] == INCORRECT ) {
! 3339: result = outcomes[ii];
! 3340: done = 1;
! 3341: }
! 3342: ii++;
! 3343: if(ii==cnt) done = 1;
! 3344: }
! 3345: }
! 3346: capa_mfree((char *)outcomes);
! 3347: if( result == 0 ) {
! 3348: result = APPROX_ANS; /* all answers are correct */
! 3349: }
! 3350: } else { /* should be ANS_OR , user answer count should always be 1 */
! 3351: if( cnt != 1 ) { return (ANS_CNT_NOT_MATCH); }
! 3352: if( p->ans_cnt == 1 ) { return (capa_check_answer(p, answers[0])); }
! 3353: result = capa_check_answer(p, answers[0]);
! 3354: ii = 1; ai = p->ans_list;
! 3355: while( (ii<p->ans_cnt) && ( (result != EXACT_ANS) && (result != APPROX_ANS) ) ) {
! 3356: result = capa_check_ans(ai,answers[0]);
! 3357: ai = ai->ans_next; ii++;
! 3358: }
! 3359: }
! 3360: return (result);
! 3361: }
! 3362:
! 3363:
! 3364:
! 3365:
! 3366:
! 3367:
! 3368:
! 3369:
! 3370: /* ========================================================================= */
! 3371: int w_getclassdir(cpath_p, cown_p, class)
! 3372: char **cpath_p; char **cown_p; char *class;
! 3373: {
! 3374: FILE *fp;
! 3375: char filename[SMALL_LINE_BUFFER];
! 3376: char *cname_p;
! 3377: int done;
! 3378: char c;
! 3379:
! 3380: sprintf(filename,"class.conf");
! 3381: if ((fp=fopen(filename,"r"))==NULL) {
! 3382: sprintf(filename,"../class.conf");
! 3383: if ((fp=fopen(filename,"r"))==NULL) {
! 3384: printf("Error: can't open %s\n",filename);
! 3385: exit (1);
! 3386: }
! 3387: }
! 3388: do {
! 3389: c_ignorewhite(fp);
! 3390: c = getc(fp); ungetc(c,fp);
! 3391: if( c != EOF ) {
! 3392: cname_p = c_getword(fp);
! 3393: *cpath_p = c_getword(fp);
! 3394: *cown_p = c_getword(fp);
! 3395: throwaway_line(fp);
! 3396: if( ! strcasecmp(cname_p, class) ) {
! 3397: done = 1;
! 3398: } else {
! 3399: free(cname_p); free(*cpath_p); free(*cown_p);
! 3400: done = 0;
! 3401: }
! 3402: } else {
! 3403: done = 1;
! 3404: }
! 3405: } while ( ! done );
! 3406: fclose(fp);
! 3407: free(cname_p);
! 3408: return (1);
! 3409: }
! 3410:
! 3411: /* ----------------------------------------------------------------- */
! 3412: /* read_capa_config gets a value out of the capa.config file
! 3413: in the read resultant string all " are removed expect for \" occurances"
! 3414: in fact all case of \ then another character become just the last
! 3415: character
! 3416:
! 3417: inputs : key_word - a string that is searched for on the lefthand side
! 3418: of an equals sign
! 3419: outputs : value - a char pointer that the value of the key_word as defined
! 3420: in the config file is copied into
! 3421: return : -1 - unable to find or acces the capa.config file
! 3422: 0 - the requested keyword was not found
! 3423: >0 - length of the string that was returned in value
! 3424: */
! 3425: /* ----------------------------------------------------------------- */
! 3426: int read_capa_config(key_word,value)
! 3427: char *key_word;char *value;
! 3428: {
! 3429: FILE *fp;
! 3430: char filename[SMALL_LINE_BUFFER];
! 3431: char left[MAX_BUFFER_SIZE],right[MAX_BUFFER_SIZE],c;
! 3432: int failed=0,done=0,num=0,result=-1,found=0,returnVal=0,i,j;
! 3433:
! 3434: sprintf(filename,"capa.config");
! 3435: if ((fp=fopen(filename,"r"))==NULL) {
! 3436: return (-1);
! 3437: }
! 3438: do {
! 3439: num = fscanf(fp,"%[^ \n\t#] = %[^\n]",left,right);
! 3440: if (num == 2) { result = strcasecmp(left,key_word); }
! 3441: if (result==0) { done=1; }
! 3442: if (num==EOF) { failed=1; }
! 3443: if (num!=2) {
! 3444: found=0;
! 3445: while(1) {
! 3446: c=fgetc(fp);
! 3447: if (found) {
! 3448: if (c!='\n') {
! 3449: ungetc(c,fp);
! 3450: break;
! 3451: }
! 3452: }
! 3453: if (c=='\n') found=1;
! 3454: if (((char)c)==((char)EOF)) break;
! 3455: }
! 3456: }
! 3457: } while (!done && !failed);
! 3458:
! 3459: fclose(fp);
! 3460:
! 3461: if (done) {
! 3462: for(i=0,j=0;i<(strlen(right)+1);i++) {
! 3463: value[j]='\0';
! 3464: if (right[i] == '\\' && (i < (strlen(right))) ) {
! 3465: i++;value[j]=right[i];j++;
! 3466: } else if (right[i] != '\"' ) {
! 3467: value[j]=right[i];j++;
! 3468: }
! 3469: }
! 3470: value[j]='\0';
! 3471: returnVal=j;
! 3472: }
! 3473: return returnVal;
! 3474: }
! 3475:
! 3476: int capa_access(const char *pathname, int mode)
! 3477: {
! 3478: pid_t euid,egid;
! 3479: struct stat status;
! 3480:
! 3481: euid=geteuid();
! 3482: egid=getegid();
! 3483: if ( -1 == stat(pathname,&status) ) { return -1; }
! 3484: /*printf("mode:%x F_OK:%x mode&F_OK:%x\n",mode,F_OK,(mode&F_OK));*/
! 3485: /*printf("st_mode:%x S_IFMT:%x st_mode&S_IFMT:%x\n",
! 3486: status.st_mode,S_IFMT,(status.st_mode&S_IFMT));*/
! 3487: if (!(status.st_mode & S_IFMT)) { return -1; }
! 3488: /*printf("euid: %d\t egid: %d\tstatus.st_uid: %d\tstatus.st_gid: %d\n",
! 3489: euid,egid,status.st_uid,status.st_gid);*/
! 3490: /*printf("mode:%x R_OK:%x mode&R_OK:%x\n",mode,R_OK,(mode&R_OK));*/
! 3491: /*printf("mode:%x W_OK:%x mode&W_OK:%x\n",mode,R_OK,(mode&R_OK));*/
! 3492: /*printf("mode:%x X_OK:%x mode&X_OK:%x\n",mode,R_OK,(mode&R_OK));*/
! 3493: if (euid==status.st_uid) {
! 3494: /*printf("here1\n");*/
! 3495: if ((mode & R_OK) && (!(status.st_mode & S_IRUSR))) { return -1; }
! 3496: if ((mode & W_OK) && (!(status.st_mode & S_IWUSR))) { return -1; }
! 3497: if ((mode & X_OK) && (!(status.st_mode & S_IXUSR))) { return -1; }
! 3498: } else {
! 3499: if (egid==status.st_gid) {
! 3500: /*printf("here2\n");*/
! 3501: if ((mode & R_OK) && (!(status.st_mode & S_IRGRP))) { return -1; }
! 3502: if ((mode & W_OK) && (!(status.st_mode & S_IWGRP))) { return -1; }
! 3503: if ((mode & X_OK) && (!(status.st_mode & S_IXGRP))) { return -1; }
! 3504: } else {
! 3505: /*printf("here3\n");*/
! 3506: if ((mode & R_OK) && (!(status.st_mode & S_IROTH))) { return -1; }
! 3507: if ((mode & W_OK) && (!(status.st_mode & S_IWOTH))) { return -1; }
! 3508: if ((mode & X_OK) && (!(status.st_mode & S_IXOTH))) { return -1; }
! 3509: }
! 3510: }
! 3511: return 0;
! 3512: }
! 3513:
! 3514: /*checks if the string is all whitespace*/
! 3515: /*returns 0 if it isn't */
! 3516: /*returns 1 if it is */
! 3517: int is_all_ws(char* answer)
! 3518: {
! 3519: int length,result=1,i;
! 3520: if (answer!=NULL) {
! 3521: length=strlen(answer);
! 3522: for(i=0;i<length;i++) {
! 3523: if (!isspace(answer[i])) {result=0;break;}
! 3524: }
! 3525: }
! 3526: return result;
! 3527: }
! 3528:
! 3529: void trim_response_ws(char* answer)
! 3530: {
! 3531: char *temp;
! 3532: int i,j=0,length;
! 3533: length=strlen(answer);
! 3534: temp=capa_malloc(length+1,1);
! 3535: strcpy(temp,answer);
! 3536: for(i=0; i<length;i++) if (!(isspace(temp[i]))) break;
! 3537: for(j=length-1;j>=0;j--) if (!(isspace(temp[j]))) break;
! 3538: temp[++j]='\0';
! 3539: strcpy(answer,&temp[i]);
! 3540: }
! 3541:
! 3542: void throwaway_line(FILE* fp)
! 3543: {
! 3544: int c;
! 3545: do {
! 3546: c = getc(fp);
! 3547: } while ( (c != '\n') && (c != EOF) );
! 3548: }
! 3549:
! 3550: char* capa_get_seat(char* studentnum,char* seatfile)
! 3551: {
! 3552: FILE* fp;
! 3553: T_student student;
! 3554: char *result,*defaultseatfile="seatingchart";
! 3555: char line[TMP_LINE_LENGTH],*lineend;
! 3556: int stuline=0,seatline=0;
! 3557:
! 3558: stuline = capa_get_student(studentnum,&student);
! 3559: if (stuline < 1 ) goto error;
! 3560: if (seatfile == NULL) seatfile=defaultseatfile;
! 3561: if ((fp=fopen(seatfile,"r"))==NULL) goto error;
! 3562: while( (stuline>seatline) && (fgets(line,TMP_LINE_LENGTH-1,fp)) ) seatline++;
! 3563: if (seatline< stuline) goto error;
! 3564: if ((lineend=index(line,' '))!=NULL) lineend='\0';
! 3565: result=capa_malloc(strlen(line)+1,1);
! 3566: strcpy(result,line);
! 3567: return result;
! 3568:
! 3569: error:
! 3570: result= capa_malloc(8,1);
! 3571: sprintf(result,"No Seat");
! 3572: return result;
! 3573:
! 3574: }
! 3575:
! 3576: void protect_log_string(char* log_string)
! 3577: {
! 3578: int i,len=strlen(log_string);
! 3579: for(i=0;i<len;i++) {
! 3580: switch (log_string[i]) {
! 3581: case '\n': case '\t': case '\r':
! 3582: log_string[i]=' ';
! 3583: break;
! 3584: }
! 3585: }
! 3586: }
! 3587:
! 3588: int capa_get_login_time(char *student_number,int set,time_t *logintime)
! 3589: {
! 3590: FILE *fp;
! 3591: int found,temp=0;
! 3592: char filename[FILE_NAME_LENGTH],line[SMALL_LINE_BUFFER];
! 3593:
! 3594: *logintime=0;
! 3595: sprintf(filename,"records/access%d.log",set);
! 3596:
! 3597: if ((fp=fopen(filename,"r"))==NULL) return (-1);
! 3598: found = 0;
! 3599: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
! 3600: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
! 3601: }
! 3602: fclose(fp);
! 3603: if (found) sscanf(rindex(line,':'),":%d",&temp);
! 3604: *logintime=(time_t)temp;
! 3605: return found;
! 3606: }
! 3607:
! 3608: /*----------------------------------------------------------*/
! 3609: /* INPUT: set the X in logX.db */
! 3610: /* OUTPUT: creates the accessX.log file if it doesn't exist */
! 3611: /* and inserts stunum:time(NULL) if stunum isn't */
! 3612: /* in ther already. */
! 3613: /* */
! 3614: /* RETURN: -1 file error */
! 3615: /* 0 already set */
! 3616: /* 1 succesfully logged a login time */
! 3617: /*----------------------------------------------------------*/
! 3618: int capa_set_login_time(char *student_number,int set)
! 3619: {
! 3620: FILE *fp;
! 3621: int errcode=0;
! 3622: int found=0;
! 3623: char filename[FILE_NAME_LENGTH],line[SMALL_LINE_BUFFER];
! 3624:
! 3625: sprintf(filename,"records/access%d.log",set);
! 3626:
! 3627: if ((fp=fopen(filename,"r"))!=NULL) {
! 3628: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
! 3629: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
! 3630: }
! 3631: fclose(fp);
! 3632: }
! 3633:
! 3634: if (found) return 0;
! 3635:
! 3636: sprintf(line,"%s:%d\n", student_number,(int)time(NULL));
! 3637: if ((fp=fopen(filename,"a+"))==NULL) return (-1);
! 3638: flockstream(fp);
! 3639: fseek(fp,0L,SEEK_END);
! 3640: if ( !fwrite((char *)line, strlen(line), 1, fp) ) {
! 3641: errcode = -1;
! 3642: } else {
! 3643: errcode = 1;
! 3644: }
! 3645: fflush(fp);
! 3646: funlockstream(fp);
! 3647: fclose(fp);
! 3648: return (errcode);
! 3649: }
! 3650: /* =||>|===================== End of capaCommon.c =====================|<||= */
! 3651:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>