File:  [LON-CAPA] / capa / capa51 / pProj / capaCgiUtils.c
Revision 1.10: download - view: text, annotated - select for diffs
Tue Jan 25 17:14:29 2000 UTC (24 years, 5 months ago) by albertel
Branches: MAIN
CVS tags: HEAD
- trime ws from all responses and from values in capa config files

    1: /* ===================================================================== */
    2: /*   copyrighted by Isaac Tsai, 1998, 1999, 2000    */
    3: /* ===================================================================== */
    4: #include <stdio.h>
    5: #include <ctype.h>
    6: #ifndef NO_STDLIB_H
    7: #include <stdlib.h>
    8: #else
    9: char *getenv();
   10: #endif
   11: #include <stdio.h>
   12: 
   13: #include "capaToken.h"
   14: #include "capaParser.h"
   15: #include "capaCommon.h"
   16: #include "ranlib.h"
   17: 
   18: #ifdef _MAIN_PROGRAM_
   19: #undef _MAIN_PROGRAM_
   20: #endif
   21: 
   22: #include "capaCGI.h"
   23: 
   24: void getword
   25: CAPA_ARG((char *word, char *line, char stop))
   26: {
   27:     int x = 0,y;
   28: 
   29:     for(x=0;((line[x]) && (line[x] != stop));x++)
   30:         word[x] = line[x];
   31: 
   32:     word[x] = '\0';
   33:     if(line[x]) ++x;
   34:     y=0;
   35: 
   36:     while((line[y++] = line[x++]));
   37: }
   38: 
   39: char *makeword
   40: CAPA_ARG((char *line, char stop))
   41: {
   42:     int x = 0,y;
   43:     char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
   44: 
   45:     for(x=0;((line[x]) && (line[x] != stop));x++)
   46:         word[x] = line[x];
   47: 
   48:     word[x] = '\0';
   49:     if(line[x]) ++x;
   50:     y=0;
   51: 
   52:     while((line[y++] = line[x++]));
   53:     return word;
   54: }
   55: 
   56: char *fmakeword
   57: CAPA_ARG((FILE *f,char  stop,int * cl))
   58: {
   59:     int wsize;
   60:     char *word;
   61:     int ll;
   62: 
   63:     wsize = 102400;
   64:     ll=0;
   65:     word = (char *) malloc(sizeof(char) * (wsize + 1));
   66: 
   67:     while(1) {
   68:         word[ll] = (char)fgetc(f);
   69:         if(ll==wsize) {
   70:             word[ll+1] = '\0';
   71:             wsize+=102400;
   72:             word = (char *)realloc(word,sizeof(char)*(wsize+1));
   73:         }
   74:         --(*cl);
   75:         if((word[ll] == stop) || (feof(f)) || (!(*cl))) {
   76:             if(word[ll] != stop) ll++;
   77:             word[ll] = '\0';
   78:             return word;
   79:         }
   80:         ++ll;
   81:     }
   82: }
   83: 
   84: char x2c
   85: CAPA_ARG((char *what))
   86: {
   87:     register char digit;
   88: 
   89:     digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
   90:     digit *= 16;
   91:     digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
   92:     return(digit);
   93: }
   94: 
   95: void unescape_url
   96: CAPA_ARG((char *url))
   97: {
   98:     register int x,y;
   99: 
  100:     for(x=0,y=0;url[y];++x,++y) {
  101:         if((url[x] = url[y]) == '%') {
  102:             url[x] = x2c(&url[y+1]);
  103:             y+=2;
  104:         }
  105:     }
  106:     url[x] = '\0';
  107: }
  108: 
  109: void plustospace
  110: CAPA_ARG((char *str))
  111: {
  112:     register int x;
  113: 
  114:     for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
  115: }
  116: 
  117: int rind
  118: CAPA_ARG((char *s,char c))
  119: {
  120:     register int x;
  121:     for(x=strlen(s) - 1;x != -1; x--)
  122:         if(s[x] == c) return x;
  123:     return -1;
  124: }
  125: 
  126: int getline
  127: CAPA_ARG((char *s,int n,FILE *f)) 
  128: {
  129:     register int i=0;
  130: 
  131:     while(1) {
  132:         s[i] = (char)fgetc(f);
  133: 
  134:         if(s[i] == CR)
  135:             s[i] = fgetc(f);
  136: 
  137:         if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
  138:             s[i] = '\0';
  139:             return (feof(f) ? 1 : 0);
  140:         }
  141:         ++i;
  142:     }
  143: }
  144: 
  145: void send_fd
  146: CAPA_ARG((FILE *f, FILE *fd))
  147: {
  148:     char c;
  149: 
  150:     while (1) {
  151:         c = fgetc(f);
  152:         if(feof(f)) return;
  153:         fputc(c,fd);
  154:     }
  155: }
  156: 
  157: int ind
  158: CAPA_ARG((char *s,char c))
  159: {
  160:     register int x;
  161: 
  162:     for(x=0;s[x];x++)
  163:         if(s[x] == c) return x;
  164: 
  165:     return -1;
  166: }
  167: 
  168: void escape_shell_cmd
  169: CAPA_ARG((char *cmd))
  170: {
  171:     register int x,y,l;
  172: 
  173:     l=strlen(cmd);
  174:     for(x=0;cmd[x];x++) {
  175:         if(ind("&;`'\"|*?~<>^()[]{}$\\",cmd[x]) != -1){
  176:             for(y=l+1;y>x;y--)
  177:                 cmd[y] = cmd[y-1];
  178:             l++; /* length has been increased */
  179:             cmd[x] = '\\';
  180:             x++; /* skip the character */
  181:         }
  182:     }
  183: }
  184: 
  185: /* ==========================================  Updated according to Frank Wolfs 
  186:    description on July 7 1997 */
  187: char *c_getpath
  188: CAPA_ARG((FILE *f)) 
  189: {
  190:   register int c;
  191:   register int idx;
  192:   char     tmp_string[MAX_BUFFER_SIZE];
  193:   char     *new_string;
  194: 
  195:   idx = 0;
  196:   tmp_string[0]='\0';
  197:   c_ignorewhite(f);
  198:   do {  
  199:     c = getc(f);
  200:     tmp_string[idx] = c;
  201:     idx++;
  202:   } while (isalnum(c) || c == '{' || c == '}' || c == '-' || c == '\\' ||
  203: 	   c == '^'   || c == '_' || c == '/' || c == '.' || c == ':' ||
  204: 	   c == '+'   || c == '*' || c == '#' || c == '!' || c == '=' || 
  205: 	   c == ';'   || c == '$' || c == '(' || c == ')' || c == '[' ||
  206: 	   c == ']'   || c == '?' || c == '>' || c == '<' || c == ',');
  207:   ungetc(c,f); idx--;
  208:   tmp_string[idx] = 0;
  209:   new_string = (char *)malloc( (idx+1)*sizeof(char) );
  210:   strncpy(new_string,tmp_string, (idx+1) );
  211:   return (new_string);
  212: }
  213: 
  214: /* ------------------------------------------------------------------------- */
  215: 
  216: void web_printheader(FILE *out)
  217: {
  218:   FILE *header;
  219:   char *buf[MAX_BUFFER_SIZE];
  220:   int amt=0;
  221: 
  222:   if ((capa_access("HTMLheader",F_OK|R_OK)!=-1) &&
  223:       (NULL!=(header=fopen("HTMLheader","r")))) {
  224:     while(0 < (amt=fread(buf,1,MAX_BUFFER_SIZE,header))) {
  225:       fwrite(buf,1,amt,out);
  226:     }
  227:     fclose(header);
  228:   } else {
  229:     fprintf(out,"<HTML><HEAD>\n");
  230:     fprintf(out,"<BODY BGCOLOR=\"#FFFFFF\" LINK=\"#0000EE\" VLINK=\"#EE1100\">\n");
  231:   }
  232: 
  233: #ifdef  CAPA_WEB
  234:   fprintf(out,"<!-- capasbin, CAPA Version %s, %s -->\n",
  235: 	  CAPA_VER,COMPILE_DATE);
  236: #else
  237:   fprintf(out,"<!-- capahtml, CAPA Version %s, %s -->\n",
  238: 	  CAPA_VER,COMPILE_DATE);
  239: #endif
  240: }
  241: 
  242: void web_printfooter(FILE *out)
  243: {
  244:   FILE *footer;
  245:   char *buf[MAX_BUFFER_SIZE];
  246:   int amt=0;
  247: 
  248:   if ((capa_access("HTMLfooter",F_OK|R_OK)!=-1) &&
  249:       (NULL!=(footer=fopen("HTMLfooter","r")))) {
  250:     while(0 < (amt=fread(buf,1,MAX_BUFFER_SIZE,footer))) {
  251:       fwrite(buf,1,amt,out);
  252:     }
  253:     fclose(footer);
  254:   } else {
  255:     fprintf(out,"</BODY></HTML>\n");
  256:   }
  257: }
  258: 
  259: int  web_getclassdir
  260: CAPA_ARG((char **cpath_p, char **cown_p, char *class))
  261: {
  262:     FILE     *fp;
  263:     char      filename[FILE_NAME_LENGTH];
  264:     char     *cname_p;
  265:     int       done;
  266:     char      c;
  267:     
  268:     sprintf(filename,"class.conf");
  269:     if ((fp=fopen(filename,"r"))==NULL) {
  270:       sprintf(filename,"../class.conf");
  271:       if ((fp=fopen(filename,"r"))==NULL) {
  272:         fprintf(stdout,"<!-- Error: can't open %s --> \n",filename); fflush(stdout);
  273:         return (2);
  274:       }
  275:     }
  276:     do {
  277:       c_ignorewhite(fp);
  278:       c = getc(fp); ungetc(c,fp);
  279:       if( c != EOF ) {
  280:         cname_p = c_getword(fp);
  281:        *cpath_p = c_getpath(fp);
  282:        *cown_p  = c_getword(fp);
  283:         throwaway_line(fp);
  284:         if( ! strcasecmp(cname_p, class) ) {
  285:           done = 1;
  286:         } else {
  287:           free(cname_p); free(*cpath_p); free(*cown_p);
  288:           done = 0;
  289:         }
  290:       } else {
  291:         done = 1;
  292:       }
  293:     } while ( ! done );
  294:     fclose(fp);
  295:     free(cname_p);
  296:     return (1);
  297: }
  298: 
  299: int web_log(log_str)char *log_str;
  300: {
  301:    FILE  *fp;       
  302:    char   filename[FILE_NAME_LENGTH];
  303: 
  304:    sprintf(filename,"web_access.log");
  305:    if ((fp=fopen(filename,"a"))==NULL) {
  306:      return -1; 
  307:    }
  308:    flockstream(fp);
  309:    fprintf(fp,"%s",log_str);fflush(fp);
  310:    funlockstream(fp);
  311:    fclose(fp);
  312:    return 0;
  313: }
  314: 
  315: int  w_log_timing(student_number,set,section,log_string)
  316: char  student_number[MAX_STUDENT_NUMBER+1];     
  317: int   set;  
  318: int   section;                                    
  319: char *log_string;                                
  320: {                                                  
  321:    char   filename[FILE_NAME_LENGTH],            
  322:          *ct;                                    
  323:    FILE  *fp;                                     
  324:    time_t t;                                 
  325: 
  326:    sprintf(filename,"records/webtiming%d.log",set);
  327:    if ((fp=fopen(filename,"a"))==NULL) {
  328:       return (-1);
  329:    }
  330:    /* CREATE LOG ENTRY */
  331:    time(&t);
  332:    ct=ctime(&t);
  333:    ct[ strlen(ct)-1 ]=0; /* Trash newline */
  334:    fprintf(fp,"%s %s %s\n",student_number,ct,log_string); fflush(fp);
  335:    fclose(fp);
  336:    return (0);
  337: }
  338: 
  339: int  w_log_attempt(student_number,set,log_string)
  340: char  student_number[MAX_STUDENT_NUMBER+1];     
  341: int   set;  
  342: char *log_string;                                
  343: {                                                  
  344:    char   filename[FILE_NAME_LENGTH],            
  345:          *ct;                                    
  346:    FILE  *fp;                                     
  347:    time_t t;                                 
  348: 
  349:    sprintf(filename,"records/weblog%d.db",set);
  350:    if ((fp=fopen(filename,"a"))==NULL) {
  351:       return (-1);
  352:    }
  353: 
  354:    /* CREATE LOG ENTRY */
  355:    time(&t);
  356:    ct=ctime(&t);
  357:    ct[ strlen(ct)-1 ]=0; /* Trash newline */
  358:    fprintf(fp,"%s %s %s\n",student_number,ct,log_string); fflush(fp);
  359:    fclose(fp);
  360:    return (0);
  361: }
  362: 
  363: int  w_log_submissions(student_number,set,log_string)
  364: char  student_number[MAX_STUDENT_NUMBER+1];     
  365: int   set;  
  366: char *log_string;                                
  367: {                                                  
  368:    char   filename[FILE_NAME_LENGTH],timeStr[FILE_NAME_LENGTH],buf2[MAX_BUFFER_SIZE];
  369:    FILE  *fp;                                     
  370:    time_t t;            
  371:    struct tm     *tmtime;
  372:    int do_log_submissions=1,result;
  373:    char buf[MAX_BUFFER_SIZE];
  374: 
  375:    result=read_capa_config("do_log_submissions",buf);
  376:    if (result != 0 && result != -1) 
  377:      if (strcasecmp(buf2,"no")==0) 
  378:        do_log_submissions=0;
  379:    if (!do_log_submissions) return 0;
  380: 
  381:    sprintf(filename,"records/websubmissions%d.db",set);
  382:    if ((fp=fopen(filename,"a"))==NULL) {
  383:      return (-1);
  384:    }
  385: 
  386:    /* CREATE LOG ENTRY */
  387:    time(&t);
  388:    tmtime=localtime(&t);
  389:    strftime(timeStr,FILE_NAME_LENGTH,"%d/%m %X",tmtime);
  390:    /*ct[ strlen(ct)-1 ]=0;*/ /* Trash newline */
  391:    protect_log_string(log_string);
  392:    fprintf(fp,"%s\t%s\t%s\n",student_number,timeStr,log_string); fflush(fp);
  393:    fclose(fp);
  394:    return (0);
  395: }
  396: 
  397: 
  398: void w_get_responses(int x,int q_idx,char* submissions_str)
  399: {
  400:   int leng, sub_idx;
  401:   char buf[MAX_BUFFER_SIZE];
  402:   if( !strncmp(g_entries[x].name,"INPUT",5) ) {
  403:     if( index(g_entries[x].name, ',' ) == NULL ) {  /* only one answer */
  404:       sscanf(g_entries[x].name,"INPUT%d",&q_idx);
  405:       if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {
  406: 	if ( ! is_all_ws(g_entries[x].val) ) {
  407: 	  g_stu_ans_pp[q_idx] = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);
  408: 	  (g_stu_ans_pp[q_idx])->a_idx  = 1;
  409: 	  (g_stu_ans_pp[q_idx])->a_str  = strsave(g_entries[x].val);
  410: 	  (g_stu_ans_pp[q_idx])->a_next = NULL;
  411: 	  trim_response_ws((g_stu_ans_pp[q_idx])->a_str);
  412: 	}
  413: 	leng = strlen( g_entries[x].val );
  414: 	if ( leng > 0 ) {
  415: 	  sprintf(buf,"%d\t%s\t",q_idx,g_entries[x].val);
  416: 	  strcat(submissions_str,buf);
  417: 	}
  418:       }
  419:     } else { /* this answer belongs to /AND answers */
  420:       sscanf(g_entries[x].name,"INPUT%d,%d",&q_idx,&sub_idx);
  421:       if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {
  422: 	if ( ! is_all_ws(g_entries[x].val) ) { 
  423: 	  StudentAnswer_t *sa_p;
  424: 	  sa_p = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);
  425: 	  sa_p->a_idx  = sub_idx;
  426: 	  sa_p->a_str  = strsave(g_entries[x].val);
  427: 	  sa_p->a_next = NULL;
  428: 	  trim_response_ws(sa_p->a_str);
  429: 	  if( g_stu_ans_pp[q_idx] == NULL ) {
  430: 	    g_stu_ans_pp[q_idx] = sa_p;
  431: 	  } else { 
  432: 	    StudentAnswer_t *sb_p;
  433: 	    for(sb_p=g_stu_ans_pp[q_idx]; sb_p->a_next; sb_p=sb_p->a_next);
  434: 	    sb_p->a_next = sa_p;
  435: 	  }
  436: 	}
  437: 	leng = strlen( g_entries[x].val );
  438: 	if ( leng > 0 ) {
  439: 	  sprintf(buf,"%d\t%s\t",q_idx,g_entries[x].val);
  440: 	  strcat(submissions_str,buf);
  441: 	}
  442:       }
  443:     }
  444:   }
  445:   if( !strncmp(g_entries[x].name,"LAST",4) ) {  
  446:     StudentAnswer_t *sa_p;  
  447:     if( index(g_entries[x].name, ',' ) == NULL ) {  /* only one answer */
  448:       sscanf(g_entries[x].name,"LAST%d",&q_idx);
  449:       if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {
  450: 	sa_p = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);
  451: 	sa_p->a_idx  = 1;
  452: 	sa_p->a_str  = strsave(g_entries[x].val);
  453: 	sa_p->a_next = NULL;
  454: 	g_last_ans_pp[q_idx] = sa_p;
  455:       }
  456:     } else {
  457:       sscanf(g_entries[x].name,"LAST%d,%d",&q_idx,&sub_idx);
  458:       if( q_idx > 0 && q_idx < MAX_PROBLEM_CNT ) {
  459: 	sa_p = (StudentAnswer_t *)capa_malloc(sizeof(StudentAnswer_t),1);
  460: 	sa_p->a_idx  = sub_idx;
  461: 	sa_p->a_str  = strsave(g_entries[x].val);
  462: 	sa_p->a_next = NULL;
  463: 	if( g_last_ans_pp[q_idx] == NULL) {
  464: 	  g_last_ans_pp[q_idx] = sa_p;
  465: 	} else {
  466: 	    StudentAnswer_t *sb_p;
  467: 	    for(sb_p=g_last_ans_pp[q_idx]; sb_p->a_next; sb_p=sb_p->a_next);
  468: 	    sb_p->a_next = sa_p;
  469: 	}
  470:       }
  471:     }
  472:   }
  473: }
  474: 
  475: /* ========================================================================= */
  476: /* Check in:      Class name     (CLASS)
  477:                   Student Number (SNUM)
  478:                   CAPA ID        (CAPAID)
  479:                   M=1
  480:    Try set:       Class name     (CLASS)
  481:                   Student Number (SNUM)
  482:                   CAPA ID        (CAPAID)
  483: 		  First question to print (STARTNUM)
  484:                   M=2
  485:    View previous: Class name     (CLASS)
  486:                   Student Number (SNUM)
  487:                   CAPA ID        (CAPAID)
  488: 		  First question to print (STARTNUM)
  489:                   View set       (VSET)
  490:                   M=3
  491:    Set summary:   
  492:                   
  493:  --------------------------------------------------------------------------- */
  494:              
  495: int  w_get_input() 
  496: {
  497:   register  int   x,m=0;
  498:   int             cl, q_idx, result = 1;
  499:   T_header        header; 
  500:   char            log_str[MAX_BUFFER_SIZE],buf[MAX_BUFFER_SIZE];
  501:   char            submissions_str[MAX_BUFFER_SIZE];
  502:   time_t          curtime;
  503:   char           *time_str,*UNKNOWN="UNKNOWN";
  504:   int             error=0;
  505:   char           *envPtr=NULL,*envPtr2=NULL;
  506: #ifdef CGI_DBUG
  507:   fprintf(g_cgi,"Entered get_input()\n"); fflush(g_cgi);
  508: #endif /* CGI_DBUG */
  509: 
  510:   envPtr=getenv("REQUEST_METHOD");
  511:   if(!envPtr) { 
  512:     fprintf(stdout,"Enviroment variable REQUEST_METHOD not set.\n");
  513:     fprintf(stdout,"CAPA is improperly installed or run, please let your \
  514: instructor know about this error.\n");
  515:     fprintf(stdout,"No tries have been deducted for the last submission.\n");
  516:     error |= 1;
  517:     return error;
  518:   }
  519:   if(strcmp(envPtr,"POST")) {
  520:         fprintf(stdout,"This script should be referenced with a METHOD of POST.\n");
  521: 	fprintf(stdout,"CAPA is improperly installed or run, please let your \
  522: instructor know about this error.\n");
  523: 	fprintf(stdout,"No tries have been deducted for the last submission.\n");
  524:         fflush(stdout);
  525: #ifdef CGI_DBUG
  526:   fprintf(g_cgi,"Request_method is not POST\n"); fflush(g_cgi);
  527: #endif /* CGI_DBUG */        
  528:         error |= 2; return (error);
  529:   }
  530:   
  531:   envPtr=getenv("CONTENT_TYPE");
  532:   if(!envPtr) { 
  533:     fprintf(stdout,"Enviroment variable CONTENT_TYPE not set.\n");
  534:     fprintf(stdout,"CAPA is improperly installed or run, please let your \
  535: instructor know about this error.\n");
  536:     fprintf(stdout,"No tries have been deducted for the last submission.\n");
  537:     fflush(stdout);
  538:     error |= 4;
  539:     return error;
  540:   }
  541:   if(strncmp(envPtr,"application/x-www-form-urlencoded",33)) {
  542:         fprintf(stdout,"This script can only be used to decode form results. \n");
  543: 	fprintf(stdout,"CAPA is improperly installed or run, please let your \
  544: instructor know about this error.\n");
  545: 	fprintf(stdout,"No tries have been deducted for the last submission.\n");
  546:         fflush(stdout);
  547: #ifdef CGI_DBUG
  548: 	fprintf(g_cgi,"CONTENT_TYPE is not application/x-www-form-urlencoded\n"); fflush(g_cgi);
  549: #endif /* CGI_DBUG */              
  550:         error |= 8; return (error);
  551:   }
  552: 
  553:   envPtr=getenv("CONTENT_LENGTH");
  554:   if(!envPtr) { 
  555:     fprintf(stdout,"Enviroment variable CONTENT_LENGTH not set.\n");
  556:     fprintf(stdout,"CAPA is improperly installed or run, please let your \
  557: instructor know about this error.\n");
  558:     fprintf(stdout,"No tries have been deducted for the last submission.\n");
  559:     error |= 16;
  560:     return error;
  561:   }
  562:   cl = atoi(envPtr);
  563: #ifdef CGI_DBUG
  564:   fprintf(g_cgi,"CONTENT_LENGTH is %d\n",cl); fflush(g_cgi);
  565: #endif /* CGI_DBUG */
  566:   for(x=0;cl && (!feof(stdin));x++) {
  567:     m=x;
  568:     g_entries[x].val = fmakeword(stdin,'&',&cl);
  569:     plustospace(g_entries[x].val);
  570:     unescape_url(g_entries[x].val);
  571:     g_entries[x].name = makeword(g_entries[x].val,'=');
  572:   }
  573:   /* ---------------------------------------------------- */
  574:   g_entered_pin = 0; g_run_mode =0;
  575:   submissions_str[0]='\0';
  576:   for(x=0; x <= m; x++) {
  577:       if( !strcmp(g_entries[x].name,"CLASS") ) {
  578:         strncpy(g_class_name,g_entries[x].val,MAX_CLASS_CHAR);
  579:       }
  580:       if( !strcmp(g_entries[x].name,"M") ) {  /* run mode */
  581:         sscanf(g_entries[x].val,"%d",&g_run_mode);
  582:       }
  583:       if( !strcmp(g_entries[x].name,"STARTNUM")) {
  584: 	sscanf(g_entries[x].val,"%d",&g_start_question);
  585:       }
  586:       if( !strcmp(g_entries[x].name,"SNUM") ) {
  587:         strncpy(g_student_number,g_entries[x].val,MAX_STUDENT_NUMBER+4);
  588:       }
  589:       if( !strcmp(g_entries[x].name,"CAPAID") ) {
  590:         sscanf(g_entries[x].val,"%d",&g_entered_pin);
  591:       }
  592:       if( !strcmp(g_entries[x].name,"SET") ) {
  593:         sscanf(g_entries[x].val,"%d",&g_set);
  594:       }
  595:       if( !strcmp(g_entries[x].name,"VSET") ) {
  596: 	if (g_entries[x].val[0] == '\0') {
  597: 	  g_vset=0;
  598: 	} else {
  599: 	  sscanf(g_entries[x].val,"%d",&g_vset);
  600: 	}
  601:       }
  602:       if( !strcmp(g_entries[x].name,"KND") ) {
  603:         sscanf(g_entries[x].val,"%d",&g_skind);
  604:       }
  605:       w_get_responses(x,q_idx,submissions_str);
  606:       free(g_entries[x].val);
  607:       free(g_entries[x].name);
  608:   }
  609:   
  610: #ifdef CGI_DBUG
  611:   fprintf(g_cgi,"DONE: Parse input\n"); fflush(g_cgi);
  612: #endif /* CGI_DBUG */
  613:   /* --------------------------------------------------------- */
  614:   /* if( strcasecmp(g_prog_name,"capacheckin") == 0 ) { */
  615:   if( g_run_mode == M_CHECKIN ) { /* capa_checkin */
  616:     time(&curtime); time_str = ctime(&curtime);
  617:     time_str[ strlen(time_str)-1 ] = 0;
  618:     envPtr=getenv("REMOTE_HOST");
  619:     if(!envPtr) { 
  620:       fprintf(stdout,"<!-- Enviroment variable REMOTE_HOST not set.-->\n");
  621:       envPtr=getenv("REMOTE_ADDR");
  622:       if(!envPtr) { 
  623: 	fprintf(stdout,"<!-- Enviroment variable REMOTE_ADDR not set.-->\n");
  624: 	envPtr=UNKNOWN;
  625: 	error |= 32;
  626:       }
  627:     }
  628: #ifdef CGI_DBUG
  629:   fprintf(g_cgi,"DONE: REMOTE_HOST\n"); fflush(g_cgi);
  630: #endif /* CGI_DBUG */
  631: 
  632:     envPtr2=getenv("HTTP_USER_AGENT");
  633:     if(!envPtr2) { 
  634:       fprintf(stdout,"<!-- Enviroment variable HTTP_USER_AGENT not set. -->\n");
  635:       envPtr2=UNKNOWN;
  636:       error |= 64;
  637:     }
  638:     sprintf(log_str,"%s\t%s\t%s\t%s\t%s\n",g_class_name,g_student_number,time_str,envPtr,envPtr2);
  639:     if (web_log(log_str) == -1 ) {
  640:       fprintf(stdout,"Unable to log access to the system. Please notify instructor\n.");
  641:       fprintf(stdout,"No tries have been deducted for the last submission.\n");
  642:       error |= 128;
  643:       return error;
  644:     }
  645:     
  646:   }
  647: #if defined(NeXT) 
  648:    getwd(g_cwd);
  649: #else
  650:    getcwd(g_cwd,255);
  651: #endif
  652:   web_getclassdir(&g_cpath, &g_cowner, g_class_name);
  653:   sprintf(g_class_fullpath,"%s/%s",g_cpath,g_class_name);
  654: #ifdef CGI_DBUG
  655:   fprintf(g_cgi,"DONE: getclassdir() [%s]\n",g_class_fullpath); fflush(g_cgi);
  656: #endif /* CGI_DBUG */
  657:   if( !capa_access(g_class_fullpath, F_OK) == 0 ) {
  658:     fprintf(stdout,"ACCESS: could not access the class directory [%s]!\n",g_class_fullpath);
  659:     fprintf(stdout,"Please exit the web browser and try accessing the system again\n");
  660:     fprintf(stdout,"No tries have been deducted for the last submission.\n");
  661:     fflush(stdout);
  662:     sprintf(log_str,"Failed to access class dir, g_class_fullpath: %s\tg_cpath: %s\tg_class_name: %s\tg_cowner: %s\tg_cwd: %s\t",
  663: 	    g_class_fullpath,g_cpath,g_class_name,g_cowner,g_cwd);
  664:     if (web_log(log_str) == -1 ) {
  665:       fprintf(stdout,"Unable to log access to the system. Please notify instructor\n.");
  666:       fflush(stdout);
  667:       error |= 256;
  668:       return error;
  669:     } 
  670: #ifdef CGI_DBUG
  671:     fprintf(g_cgi,"NO ACCESS: cannot access() [%s]\n",g_class_fullpath); fflush(g_cgi);
  672: #endif /* CGI_DBUG */      
  673:     error |= 512;
  674:     return (error);
  675:   }
  676:   /* ---------------------------------------------------- */
  677:   /*      change working directory to the class           */
  678:   /* ---------------------------------------------------- */
  679:   chdir(g_class_fullpath); /* before performing any capa*() calls */
  680: #ifdef CGI_DBUG
  681:   fprintf(g_cgi,"DONE cd to [%s]\n",g_class_fullpath); fflush(g_cgi);
  682: #endif /* CGI_DBUG */
  683: 
  684:   /* Now in proper directory, can log submissions */
  685:   if ( g_run_mode == M_CHECKANS) {
  686:     if (w_log_submissions(g_student_number,g_set,submissions_str) == -1 ) {
  687:       fprintf(stdout,"Unable to log submissions. Please notify instructor\n.");
  688:       fprintf(stdout,"No tries have been deducted for the last submission.\n");
  689:       error |= 1024;
  690:       return error; 
  691:     }
  692:   }
  693: 
  694:   result=read_capa_config("capaweb_cgibin_path",buf);
  695:   if (result != 0 && result != -1) {
  696:     g_cgibin_path=capa_malloc(strlen(buf)+1,1);
  697:     strcpy(g_cgibin_path,buf);
  698:   } else {
  699:     g_cgibin_path=capa_malloc(strlen("capa-bin")+1,1);
  700:     strcpy(g_cgibin_path,"capa-bin");
  701:   }
  702: 
  703:   if( g_entered_pin != 0 ) {
  704:       g_login_set = capa_PIN(g_student_number,999,g_entered_pin);
  705: #ifdef CGI_DBUG
  706:   fprintf(g_cgi,"Succeed in login to set %d with pin %d\n",g_login_set,g_entered_pin); fflush(g_cgi);
  707: #endif /* CGI_DBUG */   
  708:     /* ---------------------------------------------------- 
  709:       printf("Your entered capa id %d, login to set %d\n", g_entered_pin, g_login_set);
  710:       printf("The real capa id for %s is %d\n",g_student_number,capa_PIN(g_student_number,1,0));
  711:     ---------------------------------------------------- */
  712:     
  713:   } else {
  714:     fprintf(stdout,"CAPA ID entered was zero, this is not valid.\n");
  715:     fprintf(stdout,"No tries have been deducted for the last submission.\n");
  716:     fflush(stdout);
  717:     error |= 2048; return (error);
  718:   }
  719: 
  720:   if (!g_login_set) { 
  721:         fprintf(stdout,"The student ID (%s) or CAPA ID (%d) that you entered \
  722: is not listed for the class (%s) that you have selected. Please check that \
  723: you have selected the correct class on the CAPA logon page and that the \
  724: student ID and CAPA ID are correct.\n", 
  725: 		g_student_number, g_entered_pin, g_class_name);
  726:         fflush(stdout);
  727: #ifdef CGI_DBUG
  728: 	fprintf(g_cgi,"CAPA ID or student number is not valid.\n"); 
  729: 	fflush(g_cgi);
  730: #endif /* CGI_DBUG */   
  731:         error |= 4096;  return (error);
  732:   } else {
  733:       if ( g_login_set > 99 )  { 
  734:         fprintf(stdout,"The student ID (%s) or CAPA ID (%d) that you entered \
  735: is not listed for the class (%s) that you have selected. Please check that \
  736: you have selected the correct class on the CAPA logon page and that the \
  737: student ID and CAPA ID are correct.\n", 
  738: 		g_student_number, g_entered_pin, g_class_name);
  739:            fflush(stdout);
  740: #ifdef CGI_DBUG
  741: 	   fprintf(g_cgi,"CAPA ID is not valid.\n"); fflush(g_cgi);
  742: #endif /* CGI_DBUG */            
  743:            error |= 8192; return (error);
  744:       }
  745:       if(g_login_set < g_vset ) {
  746:            fprintf(stdout,"Your CAPA ID (for set %d) does not allow you to view set %d.\n",g_login_set, g_vset);
  747:            fflush(stdout);
  748: #ifdef CGI_DBUG
  749: 	   fprintf(g_cgi,"Login set %d is less than view set %d.\n",g_login_set,g_vset); fflush(g_cgi);
  750: #endif /* CGI_DBUG */ 
  751:            error |= 16384; return (error);
  752:       }
  753:       chdir(g_class_fullpath);  /* again, to make sure */
  754:       
  755:       if ( capa_get_student(g_student_number,&g_student_data) == 0 ) {
  756:            fprintf(stdout,"Entered student id is not in the class list.\n");
  757: 	   fprintf(stdout,"Please check that have selected the correct class \
  758: and have entered you student id correctly.\n");
  759:            fflush(stdout);
  760: #ifdef CGI_DBUG
  761: 	   fprintf(g_cgi,"get_student(): Student id not in the classl file.\n"); fflush(g_cgi);
  762: #endif /* CGI_DBUG */               
  763:             error |= 32768; return (error);
  764:       } else {
  765: 	 time(&curtime);
  766: 	 if (capa_get_header(&header, g_login_set))  {
  767: 	   fprintf(stdout,"This problem set is not ready yet.\n"); 
  768: 	   fflush(stdout);
  769: 	  
  770: #ifdef CGI_DBUG
  771: 	   fprintf(g_cgi,"get_header(): Problem set not ready.\n"); fflush(g_cgi);
  772: #endif /* CGI_DBUG */            
  773: 	   error |= 65536; return (error);
  774:  	 }
  775: 	 capa_mfree(header.weight);
  776: 	 capa_mfree(header.partial_credit);
  777:          /* ===> if (compare_datetime(curtime,header.open_date) < 0 ) { */
  778:          if( capa_check_date(CHECK_OPEN_DATE,g_student_number,
  779: 			     g_student_data.s_sec,g_login_set) < 0 ) {
  780:             fprintf(stdout,"This set(%d) is not yet open. Please try back later.\n",g_login_set); 
  781: 	    fflush(stdout);
  782: #ifdef CGI_DBUG
  783: 	    fprintf(g_cgi,"check_date(): Problem set not open.\n"); 
  784: 	    fflush(g_cgi);
  785: #endif /* CGI_DBUG */    
  786:             error |= 131072; return (error);
  787:          }
  788:       }
  789:   }
  790:   return (error);
  791: }
  792: 
  793: /* ============================================================================= */
  794: void        append_qtext(new_str) char *new_str;
  795: {
  796:   int ii,len;
  797:   if (new_str==NULL) return;
  798:   len=strlen(new_str);
  799: #ifdef CGI_DBUG
  800:   fprintf(g_cgi,"before: len %d; g_qchar_cnt %d; g_qsize %d\n",
  801: 	  len,g_qchar_cnt,g_qsize);
  802:   fflush(g_cgi);
  803: #endif /* CGI_DBUG */    
  804:   if (g_qchar_cnt+len>g_qsize-1) {
  805:     char *temp_text;
  806:     g_qsize=(g_qchar_cnt+len)*2;
  807:     temp_text=capa_malloc(g_qsize,sizeof(char));
  808:     strncpy(temp_text,g_question_txt,g_qchar_cnt);
  809:     capa_mfree(g_question_txt);
  810:     g_question_txt=temp_text;
  811:   }
  812:   for(ii=0;ii<len;ii++) {
  813:     g_question_txt[g_qchar_cnt+ii]=new_str[ii];
  814:   }
  815:   g_qchar_cnt += len;
  816:   g_question_txt[g_qchar_cnt+1]='\0';
  817: #ifdef CGI_DBUG
  818:   fprintf(g_cgi,"after: len %d; g_qchar_cnt %d; g_qsize %d\n",len,g_qchar_cnt,g_qsize);
  819:   fflush(g_cgi);
  820: #endif /* CGI_DBUG */    
  821: }
  822: void        append_stext(new_str) char *new_str;
  823: {
  824:   int ii,len;
  825:   if (new_str==NULL) return;
  826:   len=strlen(new_str);
  827: #ifdef CGI_DBUG
  828:   fprintf(g_cgi,"appending status{%s}\nlen %d; g_schar_cnt %d; g_ssize %d\n",
  829: 	  new_str,len,g_schar_cnt,g_ssize);
  830:   fflush(g_cgi);
  831: #endif /* CGI_DBUG */    
  832:   if (g_schar_cnt+len>g_ssize-1) {
  833:     char *temp_text;
  834:     g_ssize=(g_schar_cnt+len)*2;
  835:     temp_text=capa_malloc(g_ssize,sizeof(char));
  836:     strncpy(temp_text,g_status_txt,g_schar_cnt);
  837:     capa_mfree(g_status_txt);
  838:     g_status_txt=temp_text;
  839:   }
  840:   for(ii=0;ii<len;ii++) {
  841:     g_status_txt[g_schar_cnt+ii]=new_str[ii];
  842:   }
  843:   g_schar_cnt += len;
  844:   g_status_txt[g_schar_cnt+1]='\0';
  845: #ifdef CGI_DBUG
  846:   fprintf(g_cgi,"len %d; g_schar_cnt %d; g_ssize %d\n",len,g_schar_cnt,g_ssize);
  847:   fflush(g_cgi);
  848: #endif /* CGI_DBUG */    
  849: }
  850: /* ============================================================================= */
  851: /* ------------------------------------------------------------
  852:   printf("ENV<br>\n");
  853:   printf("SERVER_PROTOCOL:%s<br>",getenv("SERVER_PROTOCOL"));
  854:   printf("PATH_INFO:%s<br>",getenv("PATH_INFO"));
  855:   printf("PATH_TRANSLATED:%s<br>\n",getenv("PATH_TRANSLATED"));
  856:   printf("SCRIPT_NAME:%s<br>\n",getenv("SCRIPT_NAME"));
  857:   printf("QUERY_STRING:%s<br>\n",getenv("QUERY_STRING"));
  858:   printf("REMOTE_HOST:%s<br>\n",getenv("REMOTE_HOST"));
  859:   printf("REMOTE_USER:%s<br>\n",getenv("REMOTE_USER"));
  860:   printf("REMOTE_IDENT:%s<br>\n",getenv("REMOTE_IDENT"));
  861:   printf("USER_AGENT:%s<br>\n",getenv("USER_AGENT"));
  862:   printf("HTTP_USER_AGENT:%s<br>\n",getenv("HTTP_USER_AGENT"));
  863:   ------------------------------------------------------------
  864: */
  865: 
  866: /* ------------------------------------------------------ */
  867: /*   A class directory must have   */
  868: /*     records/                    */
  869: /*                                 */
  870: /*  returns: 0  structure is correct, but no set.db files */
  871: /*          -1  structure is not correct                  */
  872: /*          >=1 the last set.db                           */
  873: 
  874: int
  875: check_class_get_maxset(dir_path) char  *dir_path;
  876: {
  877:   char   f_name[1024];
  878:   int    set;
  879:   
  880:   if( capa_access(dir_path, F_OK) == 0 ) { /* class dir exists */
  881:     sprintf(f_name,"%s/records",dir_path);
  882:     if( capa_access(f_name, F_OK) == 0 ) { /* class/records dir exists */
  883:       for(set = 1; ; set++ ) {
  884:         sprintf(f_name,"%s/records/set%d.db",dir_path,set);
  885:         if(capa_access(f_name, F_OK) == -1 )  break;
  886:       }
  887:       set--;
  888:     } else {
  889:       set = -1;
  890:     }
  891:   } else {
  892:     set = -1;
  893:   } 
  894:   return (set);
  895: }
  896: 
  897: /* ------------------------------------------------------------------------- */
  898: /* Get Exam and Quiz Path                                                    */
  899: /*   return  0, 1, 2, 3                                                      */
  900: /* 0: Neither exist                                                          */
  901: /* 1: Exam.path exists                                                       */
  902: /* 2: Quiz.path exists                                                       */
  903: /* 3: Both Exam.path and Quiz.path exists                                    */
  904: /* ------------------------------------------------------------------------- */
  905: int
  906: check_exam_quiz_path()
  907: {
  908:   char  buf[MAX_BUFFER_SIZE];
  909:   int   result = 0, configResult=0;
  910:   
  911:   configResult=read_capa_config("exam_path",buf);
  912:   if (configResult != 0 && configResult != -1) {
  913:     g_exam_set = check_class_get_maxset(buf);
  914:     if(g_exam_set > 0 )  {
  915:       result = 1;
  916:       sprintf(g_exam_path,buf);
  917:     }
  918:   }
  919:   configResult=read_capa_config("quiz_path",buf);
  920:   if (configResult != 0 && configResult != -1) {
  921:     g_quiz_set = check_class_get_maxset(buf);
  922:     if(g_quiz_set > 0 )  {
  923:       result = (result | 2);
  924:       sprintf(g_quiz_path,buf);
  925:     }
  926:   }
  927:   return (result);
  928: }
  929: 
  930: 
  931: int
  932: check_termscore_option()
  933: {
  934:   char  buf[MAX_BUFFER_SIZE];
  935:   int   result = 0, configResult=0;
  936:   
  937:   configResult=read_capa_config("term_score_applet",buf);
  938:   if (configResult != 0 && configResult != -1) {
  939:     fprintf(stdout,"<!-- term_score_applet is in capa.config file -->\n");
  940:     if (strcasecmp(buf,"yes")==0) {
  941:       fprintf(stdout,"<!-- term_score_applet is YES -->\n");
  942:       result=1;
  943:     }
  944:   }
  945:   return (result);
  946: }
  947: 
  948: 
  949: 
  950: 
  951: /* ============================================================================= */
  952: void
  953: print_mainmenu(class,sn,pin)char *class; char *sn;int pin;
  954: {
  955:   char  buf[MAX_BUFFER_SIZE];
  956:   int   outcome,configResult,term_summary_button=1;
  957:   char *serverName;
  958: 
  959:   serverName=getenv("SERVER_NAME");
  960:   if (!serverName) {
  961:     fprintf(stdout,"Enviroment variable SERVER_NAME not set.\n");
  962:     fprintf(stdout,"Unable to complete actions.\n");
  963:     return;
  964:   }
  965:   
  966:   fprintf(stdout,"<TITLE>%s main menu</TITLE>\n",g_class_name);
  967:   fprintf(stdout,"<h3>%s</h3><br>\n",g_student_name);
  968:   fprintf(stdout,"<menu>\n");
  969:   fprintf(stdout,"<li><form method=\"get\" action=\"http://%s/CAPA/help.html\">",serverName);
  970:   fprintf(stdout,"<input type=\"submit\" value=\"Help\" ></form>\n");
  971: 
  972:   fprintf(stdout,"<li><form method=\"post\" ");
  973:   /* fprintf(stdout," target=\"right_frame\" "); */
  974:   sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,g_cgibin_path,g_cowner);
  975:   fprintf(stdout,"%s\n", buf);
  976:   fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",class);
  977:   fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",sn);
  978:   fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",pin);
  979:   fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_TRYSET);
  980:   fprintf(stdout,"<input type=\"hidden\" name=\"STARTNUM\" value=\"%d\">\n",1);
  981:   fprintf(stdout,"<input type=\"submit\" value=\"Try current set\" ></form>\n");
  982:   
  983:   fprintf(stdout,"<li><form method=\"post\" ");
  984:   /* fprintf(stdout," target=\"right_frame\" "); */
  985:   sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,g_cgibin_path,g_cowner);
  986:   fprintf(stdout,"%s\n", buf);
  987:   fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",class);
  988:   fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",sn);
  989:   fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",pin);
  990:   fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_VIEWPREV);
  991:   fprintf(stdout,"<input type=\"hidden\" name=\"STARTNUM\" value=\"%d\">\n",1);
  992:   fprintf(stdout,"<input type=\"submit\" value=\"View previous set:\" >");
  993:   fprintf(stdout,"<b> set:</b><input name=\"VSET\" value=\"\" size=4></form>\n");
  994:   
  995:   /*Term Summary*/
  996:   configResult=read_capa_config("term_summary_button",buf);
  997:   if (configResult != 0 && configResult != -1 ) {
  998:     if (strcasecmp(buf,"no")==0) {
  999:       term_summary_button=0;
 1000:     }
 1001:   }
 1002:   if (term_summary_button) {
 1003:     fprintf(stdout,"<li><form method=\"post\" ");
 1004:     /* fprintf(stdout," target=\"right_frame\" "); */
 1005:     sprintf(buf,"action=\"http://%s/%s/capahtml\">",serverName,g_cgibin_path);
 1006:     fprintf(stdout,"%s\n", buf);
 1007:     fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",class);
 1008:     fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",sn);
 1009:     fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",pin);
 1010:     fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_VIEWSUMM);
 1011:     fprintf(stdout,"<input type=\"submit\" value=\"Display term summary\" ></form>\n");
 1012:   }
 1013: 
 1014:   outcome = check_exam_quiz_path();
 1015:   if( outcome & 1 ) {  /* exam summary */
 1016:     fprintf(stdout,"<li><form method=\"post\" ");
 1017:     /* fprintf(stdout," target=\"right_frame\" "); */
 1018:     sprintf(buf,"action=\"http://%s/%s/capahtml\">",serverName,g_cgibin_path);
 1019:     fprintf(stdout,"%s\n", buf);
 1020:     fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",class);
 1021:     fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",sn);
 1022:     fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",pin);
 1023:     fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_EXAMSUMM);
 1024:     fprintf(stdout,"<input type=\"submit\" value=\"Display Exam summary\" ></form>\n");
 1025:   }
 1026:   if( outcome & 2 ) { /* Quiz summary */
 1027:     fprintf(stdout,"<li><form method=\"post\" ");
 1028:     /* fprintf(stdout," target=\"right_frame\" "); */
 1029:     sprintf(buf,"action=\"http://%s/%s/capahtml\">",serverName,g_cgibin_path);
 1030:     fprintf(stdout,"%s\n", buf);
 1031:     fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",class);
 1032:     fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",sn);
 1033:     fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",pin);
 1034:     fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\" >\n",M_QUIZSUMM );
 1035:     fprintf(stdout,"<input type=\"submit\" value=\"Display Quiz summary\" ></form>\n");
 1036:   }
 1037:   outcome = check_termscore_option();
 1038:   fprintf(stdout,"<!-- Outcome of check_termscore_option()=%d -->\n",outcome);
 1039:   /*Termscore Button*/
 1040:   if( outcome ) {
 1041:     fprintf(stdout,"<li><form method=\"post\" ");
 1042:    sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,g_cgibin_path,g_cowner);
 1043:     fprintf(stdout,"%s\n", buf);
 1044:     fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",class);
 1045:     fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",sn);
 1046:     fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",pin);
 1047:     fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\" >\n",M_TERMSCORE );
 1048:     fprintf(stdout,"<input type=\"submit\" value=\"Extrapolate Term score\" ></form>\n");
 1049:   }
 1050:   /*Exit Button*/
 1051:   fprintf(stdout,"<TD><form method=\"get\" action=\"http://%s/CAPA/class.html\">",serverName);
 1052:   fprintf(stdout,"<input type=\"button\" value=\"Exit\" onclick=\"window.close()\"></form></TD>");
 1053: 
 1054:   fprintf(stdout,"</menu>\n"); fflush(stdout);
 1055:   
 1056: }
 1057: 
 1058: /* ====================================================================================== */
 1059: void
 1060: print_page_header(mode,num_quest) int mode;int num_quest;
 1061: {
 1062:   char   buf[MAX_BUFFER_SIZE], discussdir[MAX_BUFFER_SIZE];
 1063:   char *serverName;
 1064:   int    configResult,term_summary_button=1;
 1065: 
 1066:   serverName=getenv("SERVER_NAME");
 1067:   if (!serverName) {
 1068:     fprintf(stdout,"Enviroment variable SERVER_NAME not set.\n");
 1069:     fprintf(stdout,"Unable to complete actions.\n");
 1070:     return;
 1071:   }
 1072:   
 1073:   /* now done in the .qz file
 1074:   fprintf(stdout,"<TITLE>%s set%d</TITLE>",g_class_name,g_login_set);
 1075:   if( mode == VIEW_PREVIOUS_MODE ) {
 1076:     fprintf(stdout,"<H2>%s set%d</H2>\n",g_class_name,g_vset);
 1077:   } else {
 1078:     fprintf(stdout,"<H2>%s set%d</H2>\n",g_class_name,g_login_set);
 1079:   }
 1080:   fprintf(stdout,"<H3>%s</H3>\n",g_student_data.s_nm);
 1081:   */
 1082:   
 1083:   fprintf(stdout,"<A NAME=\"TOP\"></A>");
 1084:   fprintf(stdout,"<TABLE cellpadding=0 cellspacing=0 border=0>\n<TR><TD>");
 1085: 
 1086: 
 1087:   /*Term summary button*/
 1088:   configResult=read_capa_config("term_summary_button",buf);
 1089:   if (configResult != 0 && configResult != -1 ) {
 1090:     if (strcasecmp(buf,"no")==0) {
 1091:       term_summary_button=0;
 1092:     }
 1093:   }
 1094: #ifdef CGI_DBUG
 1095:   fprintf(g_cgi,"buf: %s\ntermsum: %d\n",buf,term_summary_button); fflush(g_cgi);
 1096: #endif /* CGI_DBUG */ 
 1097: 
 1098:   if (term_summary_button) {
 1099:     fprintf(stdout,"<form method=\"post\" ");
 1100:     sprintf(buf,"action=\"http://%s/%s/capahtml\">",serverName,g_cgibin_path);
 1101:     fprintf(stdout,"%s\n", buf);
 1102:     fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",g_class_name);
 1103:     fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",g_student_number);
 1104:     fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",g_entered_pin);
 1105:     fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_VIEWSUMM);
 1106:     fprintf(stdout,"<input type=\"submit\" value=\"Term summary\" ></form></TD>\n");
 1107:   }
 1108: 
 1109:   /*Exit Button*/
 1110:   fprintf(stdout,"<TD><form method=\"get\" action=\"http://%s/CAPA/class.html\">",serverName);
 1111:   fprintf(stdout,"<input type=\"button\" value=\"Exit\" onclick=\"window.close()\"></form></TD>");
 1112:   /*help button*/
 1113:   if (mode != VIEW_PREVIOUS_MODE) {
 1114:     fprintf(stdout,"<TD><form method=\"get\" action=\"http://%s/CAPA/help.html\">",serverName);
 1115:     fprintf(stdout,"<input type=\"submit\" value=\"Help\"></form></TD>");
 1116:   }
 1117: 
 1118:   /*Reload button*/
 1119:   fprintf(stdout,"<TD><form method=\"post\" ");
 1120:   sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,g_cgibin_path,g_cowner);
 1121:   fprintf(stdout,"%s\n", buf);
 1122:   fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",g_class_name);
 1123:   fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",g_student_number);
 1124:   fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",g_entered_pin);
 1125:   fprintf(stdout,"<input type=\"hidden\" name=\"STARTNUM\" value=\"%d\">\n",g_start_question);
 1126:   if (mode == VIEW_PREVIOUS_MODE ) {
 1127:     fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_VIEWPREV);
 1128:     fprintf(stdout,"<input type=\"hidden\" name=\"VSET\" value=\"%d\" size=4>\n",g_vset);
 1129:   } else {
 1130:     fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_TRYSET);
 1131:   }
 1132:   fprintf(stdout,"<input type=\"submit\" value=\"Reload\" >\n</form></TD>");
 1133: #ifdef NOT_DEFINED
 1134:   /* Next Button */
 1135:   if ( (!(g_num_questions_per_page==ALL_QUESTIONS)) && 
 1136:        ((g_num_questions_per_page+g_start_question)<num_quest)) {
 1137:     fprintf(stdout,"<TD><form method=\"post\" ");
 1138:     sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,g_cgibin_path,g_cowner);
 1139:     fprintf(stdout,"%s\n", buf);
 1140:     fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",g_class_name);
 1141:     fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",g_student_number);
 1142:     fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",g_entered_pin);
 1143:     fprintf(stdout,"<input type=\"hidden\" name=\"STARTNUM\" value=\"%d\">\n",g_start_question+g_num_questions_per_page);
 1144:     if (mode == VIEW_PREVIOUS_MODE ) {
 1145:       fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_VIEWPREV);
 1146:       fprintf(stdout,"<input type=\"hidden\" name=\"VSET\" value=\"%d\" size=4>\n",g_vset);
 1147:     } else {
 1148:       fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_TRYSET);
 1149:     }
 1150:     fprintf(stdout,"<input type=\"submit\" value=\"Next Page\" >\n</form></TD>");
 1151:   }
 1152: 
 1153:   /* Previous Button */
 1154:   if ( (!(g_num_questions_per_page==ALL_QUESTIONS)) && (g_start_question > 1)) {
 1155:     fprintf(stdout,"<TD><form method=\"post\" ");
 1156:     sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,g_cgibin_path,g_cowner);
 1157:     fprintf(stdout,"%s\n", buf);
 1158:     fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",g_class_name);
 1159:     fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",g_student_number);
 1160:     fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",g_entered_pin);
 1161:     fprintf(stdout,"<input type=\"hidden\" name=\"STARTNUM\" value=\"%d\">\n",g_start_question-g_num_questions_per_page);
 1162:     if (mode == VIEW_PREVIOUS_MODE ) {
 1163:       fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_VIEWPREV);
 1164:       fprintf(stdout,"<input type=\"hidden\" name=\"VSET\" value=\"%d\" size=4>\n",g_vset);
 1165:     } else {
 1166:       fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_TRYSET);
 1167:     }
 1168:     fprintf(stdout,"<input type=\"submit\" value=\"Previous Page\" >\n</form></TD>");
 1169:   }
 1170: #endif
 1171:   /* Goto Button */
 1172:   if (!(g_num_questions_per_page==ALL_QUESTIONS)) {
 1173:     int idx,numquest;
 1174:     T_header header;
 1175:     fprintf(stdout,"<TD><form method=\"post\" ");
 1176:     sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,g_cgibin_path,g_cowner);
 1177:     fprintf(stdout,"%s\n", buf);
 1178:     fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",g_class_name);
 1179:     fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",g_student_number);
 1180:     fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",g_entered_pin);
 1181:     fprintf(stdout,"<input type=\"submit\" value=\"Goto\" >");
 1182:     fprintf(stdout,"<b>Problem:</b><input name=\"STARTNUM\" value=\"\" size=4>\n");
 1183:     if (mode == VIEW_PREVIOUS_MODE ) {
 1184:       fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_VIEWPREV);
 1185:       fprintf(stdout,"<input type=\"hidden\" name=\"VSET\" value=\"%d\" size=4>\n",g_vset);
 1186:     } else {
 1187:       fprintf(stdout,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_TRYSET);
 1188:     }
 1189: 
 1190:     if (!capa_get_header(&header, g_login_set)) {
 1191:       numquest=atoi(header.num_questions);
 1192:       capa_mfree(header.weight);
 1193:       capa_mfree(header.partial_credit);
 1194:       for(idx=0;idx<numquest;idx++) {
 1195: 	preserve_last_answer(idx,1);
 1196:       }
 1197:     }
 1198:     fprintf(stdout,"</form></TD>");
 1199:   }
 1200: 
 1201:   /*Discuss Button*/
 1202: 
 1203:   sprintf(discussdir,"%s/discussion/%d",g_class_fullpath,g_login_set);
 1204:   if ( access(discussdir,F_OK) == 0 ) {
 1205:     fprintf(stdout,"<TD><form method=\"post\" ");
 1206:     sprintf(buf,"action=\"http://%s/%s/%s/capadiscuss\">",serverName,g_cgibin_path,g_cowner);
 1207:     fprintf(stdout,"%s\n", buf);
 1208:     fprintf(stdout,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",g_class_name);
 1209:     fprintf(stdout,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",g_student_number);
 1210:     fprintf(stdout,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",g_entered_pin);
 1211:     fprintf(stdout,"<input type=\"hidden\" name=\"SETID\" value=\"%d\">\n",g_login_set);
 1212:     fprintf(stdout,"<input type=\"submit\" value=\"Discuss\" >\n</form></TD>");
 1213:   }
 1214: 
 1215:   fprintf(stdout,"\n</TR></TABLE>\n");
 1216:   fflush(stdout);    
 1217: }
 1218: 
 1219: void create_status_line(int mode,int question_cnt, T_entry* entry)
 1220: {
 1221:   char          buf[MAX_BUFFER_SIZE];
 1222:   int           idx,configResult,status_line_length;
 1223: 
 1224:   configResult=read_capa_config("web_status_line_length",buf);
 1225:   if (configResult != 0 && configResult != -1 ) {
 1226:     if (sscanf(buf,"%d",&status_line_length)==0) {
 1227:       status_line_length=question_cnt;
 1228:     }
 1229:   } else {
 1230:     status_line_length=question_cnt;
 1231:   }
 1232: 
 1233:   append_stext("<TABLE cellpadding=0 cellspacing=0 border=0><TR>");
 1234:   append_stext("<TD><b><u>Go to problem</u>  </b></TD><TD></TD>");
 1235:   for(idx=0; idx < status_line_length;idx++ ) {
 1236:     sprintf(buf,"<TD ALIGN=center VALIGN=bottom>[%d]</TD>",idx+1);
 1237:     append_stext(buf);
 1238:   }
 1239:   for(idx = 0; idx < question_cnt; idx++ ) {
 1240:     if ( !(idx%status_line_length) ) {
 1241:       sprintf(buf,"</TR><TR><TD ALIGN=left>%d-%d</TD><TD ALIGN=right>Status: </TD>",
 1242: 		   idx+1,idx+status_line_length);
 1243:       append_stext(buf);
 1244:     }
 1245:     if ((idx >= g_start_question-1) && 
 1246: 	 (((g_num_questions_per_page == ALL_QUESTIONS)) || 
 1247: 	   (idx < (g_start_question+g_num_questions_per_page-1)))) {
 1248:       sprintf(buf,"<TD ALIGN=center VALIGN=bottom><A href=\"#P%d\">",idx+1);
 1249:     } else {
 1250:       sprintf(buf,"<TD ALIGN=center VALIGN=bottom>");
 1251:     }
 1252:     append_stext(buf);
 1253:     if ( (mode == CHECK_ANSWER_MODE) && g_log_string[idx] == '-') {
 1254:       if (g_inhibit_response && (entry->answers[idx]!='-')) {
 1255: 	sprintf(buf,"A");
 1256:       } else {
 1257: 	sprintf(buf,"%c",entry->answers[idx]); 
 1258:       }
 1259:     } else {
 1260:       if (g_inhibit_response && (entry->answers[idx]!='-')) {
 1261: 	sprintf(buf,"<b>A</b>");
 1262:       } else {
 1263: 	if ( mode == CHECK_ANSWER_MODE ) {
 1264: 	  sprintf(buf,"<b>%c</b>",g_log_string[idx]);
 1265: 	} else {
 1266: 	  sprintf(buf,"<b>%c</b>",entry->answers[idx]);
 1267: 	}
 1268:       }
 1269:     }
 1270:     append_stext(buf);
 1271:     if ((idx >= g_start_question-1) && 
 1272: 	 (((g_num_questions_per_page == ALL_QUESTIONS)) || 
 1273: 	   (idx < (g_start_question+g_num_questions_per_page-1)))) {
 1274:       sprintf(buf,"</A></TD>");
 1275:     } else {
 1276:       sprintf(buf,"</TD>");
 1277:     }
 1278:     append_stext(buf);
 1279:   }
 1280:   append_stext("</TR></TABLE>\n");
 1281: }
 1282: 
 1283: /* -------------------------------- called by try set, view previous, check answer */
 1284: void
 1285: print_quizz(class_dir,c_owner,class,sn,pin,set,mode)
 1286: char *class_dir; char *c_owner;char *class;char *sn;int pin;int set;int mode;
 1287: {
 1288:   extern int    Parsemode_f;
 1289:   extern char  *StartText_p;
 1290:   extern char  *EndText_p;
 1291:   Problem_t    *first_prob, *prob_idx;
 1292:   int           result, question_idx, question_cnt, idx, view_assignment_after_due=1;
 1293:   int           q_leng, display_ans=1, configResult;
 1294:   int           view_assignments_after_due=1;
 1295:   char          buf[MAX_BUFFER_SIZE];
 1296:   char          class_fullpath[FILE_NAME_LENGTH];
 1297:   T_entry       entry;
 1298:   T_header      header;
 1299:   long          offset;
 1300:   double        a;
 1301:   char          cmp_ans[MAX_BUFFER_SIZE],date_str[DATE_BUFFER];
 1302:   time_t        curtime;
 1303:   char         *serverName;
 1304: 
 1305:   serverName=getenv("SERVER_NAME");
 1306:   if (!serverName) {
 1307:     fprintf(stdout,"Enviroment variable SERVER_NAME not set.\n");
 1308:     fprintf(stdout,"Unable to complete actions.\n");
 1309:     return;
 1310:   }
 1311: 
 1312:   sprintf(class_fullpath,"%s/%s",class_dir,class);
 1313:   
 1314:   /*
 1315:   chdir(class_fullpath);
 1316:   */
 1317: #ifdef CGI_DBUG
 1318:   fprintf(g_cgi,"enter print_quizz() %s, mode:%d\n",class_fullpath,mode); fflush(g_cgi);
 1319: #endif /* CGI_DBUG */ 
 1320: 
 1321:   /* get configuration options */
 1322:   configResult=read_capa_config("num_questions_per_page",buf);
 1323:   if (configResult != 0 && configResult != -1 ) {
 1324:     if (sscanf(buf,"%d",&g_num_questions_per_page)==0) {
 1325:       g_num_questions_per_page=ALL_QUESTIONS;
 1326:     }
 1327:   } else {
 1328:     g_num_questions_per_page=ALL_QUESTIONS;
 1329:   }
 1330: 
 1331:   view_assignments_after_due=capa_check_option(OPTION_VIEW_PROBLEMS_AFTER_DUE,
 1332: 					       set,g_student_data.s_sec);
 1333:   if (view_assignments_after_due < 0 ) view_assignments_after_due=1;
 1334:   g_inhibit_response=capa_check_option(OPTION_INHIBIT_RESPONSE,set,g_student_data.s_sec);
 1335:   if (g_inhibit_response < 0 ) g_inhibit_response=0;
 1336: 
 1337: #ifdef CGI_DBUG
 1338:   fprintf(g_cgi,"Set %d, Section%d, ViewAssign? %d, Inhibit Resp? %d\n",set,
 1339: 	  g_student_data.s_sec,view_assignments_after_due,
 1340: 	  g_inhibit_response); 
 1341:   fflush(g_cgi);
 1342: #endif /* CGI_DBUG */ 
 1343: 
 1344:   time(&curtime);
 1345:   offset=capa_get_entry(&entry,sn,set);          /* <-------- capa*() call  ---- */
 1346:   if( mode == VIEW_PREVIOUS_MODE ) {
 1347:     if( view_assignment_after_due ) {
 1348:       if( capa_check_date(CHECK_OPEN_DATE,g_student_number,
 1349: 			  g_student_data.s_sec,set) < 0 ) {
 1350: 	append_qtext("This set is not yet open.\n");
 1351: 	return ;
 1352:       }
 1353:     } else {
 1354:       if( (capa_check_date(CHECK_ANS_DATE,g_student_number,
 1355: 			   g_student_data.s_sec,set) < 0) &&
 1356: 	  (capa_check_date(CHECK_DUE_DATE,g_student_number,
 1357: 			   g_student_data.s_sec,set) > 0) ) {
 1358: 	append_qtext("This set is not yet available to be viewed.\n");
 1359: 	return ;
 1360:       }
 1361:     }
 1362:     if( capa_check_date(CHECK_ANS_DATE,g_student_number,
 1363: 			g_student_data.s_sec,set) < 0 ) {
 1364:       display_ans = 0;
 1365:     }
 1366:   } 
 1367:   g_passdue = 0;
 1368:   if( mode == CHECK_ANSWER_MODE || 
 1369:       ( (!view_assignment_after_due) && mode == TRY_SET_MODE)) {
 1370:     if( capa_check_date(CHECK_DUE_DATE,g_student_number,
 1371: 			g_student_data.s_sec,set) > 0 ) {
 1372:        capa_get_date(CHECK_DUE_DATE,g_student_number,
 1373: 		     g_student_data.s_sec,set,date_str);
 1374:        sprintf(buf,"SORRY, the due date was: %s\n",date_str);
 1375:        append_qtext(buf);
 1376:        g_passdue = 1;
 1377:     }
 1378:   }
 1379: 
 1380:   if ((mode==CHECK_ANSWER_MODE) || (mode== TRY_SET_MODE))
 1381:     capa_set_login_time(g_student_number,set);
 1382: 
 1383:   capa_get_header(&header,set);
 1384: 
 1385:   sscanf(header.num_questions,"%d",&question_cnt);
 1386:   print_page_header(mode,question_cnt);
 1387: 
 1388: #ifdef CGI_DBUG
 1389:   fprintf(g_cgi,"DONE page header\n"); fflush(g_cgi);
 1390: #endif /* CGI_DBUG */
 1391: 
 1392:   if(offset < 0 ) offset = - offset;
 1393:   
 1394:   Parsemode_f = HTML_MODE; /* WEB_MODE */
 1395:   result = capa_parse(set, &first_prob, sn, &question_cnt,NULL);  /* <-- capa*() call */
 1396: 
 1397: #ifdef CGI_DBUG
 1398:   fprintf(g_cgi,"DONE capa_parse() [%d], pass due=%d\n",result,g_passdue); fflush(g_cgi);
 1399: #endif /* CGI_DBUG */
 1400: 
 1401:   if (StartText_p) printf(StartText_p);
 1402:  
 1403: #ifdef CGI_DBUG
 1404:   fprintf(g_cgi,"DONE Start Text\n"); fflush(g_cgi);
 1405: #endif /* CGI_DBUG */
 1406: 
 1407:   if ( result != 0 ) {
 1408:      if( !g_passdue ) {
 1409:        append_qtext("<FORM method=\"post\" ");
 1410:        sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,
 1411: 	       g_cgibin_path,c_owner);
 1412:        append_qtext(buf);
 1413:        sprintf(buf,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",class); append_qtext(buf);
 1414:        sprintf(buf,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",sn);          append_qtext(buf);
 1415:        sprintf(buf,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",pin);       append_qtext(buf);
 1416:        sprintf(buf,"<input type=\"hidden\" name=\"SET\" value=\"%d\">\n",set);          append_qtext(buf);
 1417:        sprintf(buf,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_CHECKANS); append_qtext(buf);
 1418:        sprintf(buf,"<input type=\"hidden\" name=\"STARTNUM\" value=\"%d\">\n",g_start_question); append_qtext(buf);
 1419:        append_qtext("\n<OL>\n");
 1420:      }
 1421: 
 1422:      for(idx=0;idx<question_cnt;idx++) {         /* prepare log string and new database entry */
 1423:        g_new_answerdb[idx] = entry.answers[idx];
 1424:        g_log_string[idx]   = '-';
 1425:        sscanf(entry.tries + 3*idx,"%d,",&(g_tried[idx]) );
 1426:      }
 1427:      g_new_answerdb[question_cnt]=0;  g_log_string[question_cnt]=0;
 1428:      prob_idx = first_prob;
 1429:      for( question_idx = 0; question_idx < question_cnt; 
 1430: 	  question_idx++,prob_idx = prob_idx->next ) {
 1431: #ifdef CGI_DBUG
 1432:   fprintf(g_cgi,"quetion_idx: %d, g_start_question:%d, g_num_que: %d\n",
 1433: 	  question_idx,g_start_question,g_num_questions_per_page); fflush(g_cgi);
 1434: #endif /* CGI_DBUG */        
 1435:          if ((question_idx < g_start_question-1) 
 1436: 	     ||
 1437: 	     (((!(g_num_questions_per_page == ALL_QUESTIONS)) 
 1438: 	       && 
 1439: 	       (question_idx >= (g_start_question+g_num_questions_per_page-1))))) {
 1440: 	   preserve_last_answer(question_idx,0);
 1441: 	   continue;
 1442: 	 }
 1443:          if( !g_passdue ) {
 1444:            sprintf(buf,"<A NAME=\"P%d\"></A>",question_idx+1);  append_qtext(buf);
 1445: 	   /*	   if (!((question_idx == (g_start_question-1)) || (question_idx == 0))) {
 1446: 	     append_qtext("<A href=\"#TOP\">Top</A>");
 1447: 	     sprintf(buf,"&nbsp;&nbsp;<A href=\"#P%d\">Next</A>",question_idx+2);  append_qtext(buf);
 1448: 	     }*/
 1449: 	   if (prob_idx->question != NULL) {
 1450: 	     q_leng = strlen(prob_idx->question);
 1451: 	     if ( !prob_idx->show_br ) {
 1452: 	       append_qtext(prob_idx->question);
 1453: 	     } else {
 1454: 	       for(idx=0;idx<q_leng;idx++) {
 1455: 		 if ( g_qchar_cnt+2 >= g_qsize ) {
 1456: 		   char *temp_text;
 1457: 		   g_qsize=g_qchar_cnt*2;
 1458: 		   temp_text=capa_malloc(g_qsize,sizeof(char));
 1459: 		   strncpy(temp_text,g_question_txt,g_qsize);
 1460: 		   capa_mfree(g_question_txt);
 1461: 		   g_question_txt=temp_text;		 
 1462: 		 }
 1463: 		 g_question_txt[g_qchar_cnt]=prob_idx->question[idx];
 1464: 		 g_qchar_cnt++;
 1465: 		 if(prob_idx->question[idx] == '\n' ) {
 1466: 		   append_qtext("<br>\n");
 1467: 		 }
 1468: 	       }
 1469: 	     }
 1470: 	   }
 1471:          }
 1472:          if(mode == VIEW_PREVIOUS_MODE) { /* VIEW_PREVIOUS_MODE */
 1473:            if( display_ans ) {
 1474:              if( prob_idx->ans_type == ANSWER_IS_FLOAT ) {
 1475:                  a = (double)atof(prob_idx->answer);
 1476:                  sprintf(cmp_ans,prob_idx->ans_fmt, a);
 1477:              } else {
 1478:                  strcpy(cmp_ans,prob_idx->answer);
 1479:              }
 1480:              if( prob_idx->ans_unit ) {
 1481:                  sprintf(buf,"<p><tt><b>Answer:</b> %s %s</tt><br>\n",cmp_ans, prob_idx->unit_str); 
 1482:              } else {
 1483:                  sprintf(buf,"<p><tt><b>Answer:</b> %s</tt><br>\n",cmp_ans); 
 1484:              }
 1485:              append_qtext(buf);
 1486: 	     if ( prob_idx->explain) {
 1487: 	       sprintf(buf,"<p><b>Explanation: </b>\n<p>%s<br>\n",prob_idx->explain);
 1488: 	       append_qtext(buf);
 1489: 	     }
 1490:            }
 1491:          } else { /* could be TRY_SET_MODE, CHECK_ANSWER_MODE */
 1492:            
 1493:            if( g_passdue ) {
 1494:              get_response(header.partial_credit[question_idx],entry.answers[question_idx],question_idx,prob_idx);
 1495:            }else{
 1496: 	     if (g_inhibit_response) {
 1497: 	       print_inhibited_response(header.partial_credit[question_idx],entry.answers[question_idx],question_idx,prob_idx);
 1498: 	     } else {
 1499: 	       print_response(header.partial_credit[question_idx],entry.answers[question_idx],question_idx,prob_idx); 
 1500: 	     }
 1501:              append_qtext("<br>\n");
 1502:              if( (g_tried[question_idx] >= prob_idx->show_hint) || 
 1503: 		 (entry.answers[question_idx]=='Y') ||
 1504: 		 (entry.answers[question_idx]=='y')) {
 1505:                if( prob_idx->hint ) {
 1506:                  sprintf(buf,"<p><B>Hint: </B>%s\n<br>\n", prob_idx->hint);
 1507:                  append_qtext(buf);
 1508:                }
 1509:              }
 1510:            }
 1511:          }
 1512:      }   /* ------------------------------------- end displaying each problem */
 1513:      append_qtext("\n</OL>\n");
 1514:      if( EndText_p )   append_qtext(EndText_p);
 1515:      free_problems(first_prob);
 1516: 
 1517: #ifdef CGI_DBUG
 1518:   fprintf(g_cgi,"End display each problem\n"); fflush(g_cgi);
 1519: #endif /* CGI_DBUG */
 1520: 
 1521:      if( mode == CHECK_ANSWER_MODE ) {  /* update the record database */
 1522:        if( !g_passdue ) {
 1523:          for(idx=0;idx<question_cnt;idx++){
 1524:            if( g_new_answerdb[idx] != entry.answers[idx]) { 
 1525:              entry.answers[idx] = g_new_answerdb[idx];
 1526:            }
 1527:            if(g_tried[idx] < 10 ) {
 1528:              entry.tries[3*idx]   = ' ';
 1529:              entry.tries[3*idx+1] = g_tried[idx] + '0';
 1530:              if(idx < question_cnt-1)  entry.tries[3*idx+2] = ',';
 1531:            } else {
 1532:              entry.tries[3*idx]   = (int)(g_tried[idx]/10) + '0';
 1533:              entry.tries[3*idx+1] = (g_tried[idx] % 10) + '0';
 1534:              if(idx < question_cnt-1)  entry.tries[3*idx+2] = ',';
 1535:            }
 1536:          }
 1537:          capa_set_entry(&entry,sn,set,offset);                     /* <-------- capa*() call */
 1538: 
 1539: #ifdef CGI_DBUG
 1540: 	 fprintf(g_cgi,"DONE set db entry\n"); fflush(g_cgi);
 1541: #endif /* CGI_DBUG */
 1542: 
 1543: 	 create_status_line(mode,question_cnt,&entry);
 1544:        } 
 1545:        if (w_log_attempt(g_student_number,set,g_log_string) == -1 ) {
 1546: 	 fprintf(stdout,"<BOLD>Unable to log attempt. Please notify instructor.</BOLD>\n");
 1547:        }
 1548:      }
 1549: #ifdef CGI_DBUG
 1550:      fprintf(g_cgi,"DONE check answer mode\n"); fflush(g_cgi);
 1551: #endif /* CGI_DBUG */
 1552:      
 1553:      if( (mode == TRY_SET_MODE && !g_passdue)  || 
 1554: 	 mode == VIEW_PREVIOUS_MODE) {
 1555:        create_status_line(mode,question_cnt,&entry);
 1556:      }
 1557:      
 1558:      if( !g_passdue ) {
 1559:        sprintf(buf,"</ul></form>\n"); append_qtext(buf);
 1560:      }
 1561:   }
 1562: }
 1563: 
 1564: /*if the assignment is passedue we come here to get what the answer was just in case*/
 1565: void
 1566: get_response(char pcr,char u_db,int q_idx,Problem_t *p)
 1567: {
 1568:   if( pcr == '0' || p->ans_type==ANSWER_IS_SUBJECTIVE ) { /* not hand-graded question */
 1569:      switch(u_db) {  /* what's from the user record */
 1570:        case 'Y': break;
 1571:        case 'y': break;
 1572:        case '-':
 1573:                if(g_stu_ans_pp[q_idx+1] != NULL ) log_user_ans(q_idx,p);
 1574:                break;
 1575:        case 'E':
 1576:        case 'e': break;
 1577:        case 'n': break;
 1578:        case 'N':
 1579:        case '0': case '1': case '2': case '3': case '4': 
 1580:        case '5': case '6': case '7': case '8': case '9':
 1581:                if(g_stu_ans_pp[q_idx+1] != NULL ) log_user_ans(q_idx,p);
 1582:                break;
 1583:        default:
 1584: 	      break;
 1585:      }
 1586:    }
 1587: }
 1588: 
 1589: void display_last_answer(int q_idx)
 1590: {
 1591:   char       buf[MAX_BUFFER_SIZE];  
 1592:   StudentAnswer_t  *sa_p;
 1593: #ifdef CGI_DBUG
 1594:   fprintf(g_cgi,"Enter display_last_answer() [%d]\n",q_idx); fflush(g_cgi);
 1595: #endif /* CGI_DBUG */
 1596:   if(g_stu_ans_pp[q_idx+1] != NULL) {
 1597:     sa_p=g_stu_ans_pp[q_idx+1];
 1598:   } else {
 1599:     if (g_last_ans_pp[q_idx+1] != NULL) {
 1600:       sa_p=g_last_ans_pp[q_idx+1];
 1601:     } else {
 1602:       return;
 1603:     }
 1604:   }
 1605:   if (sa_p->a_next == NULL) {
 1606:     sprintf(buf,"<input type=\"hidden\" name=\"LAST%02d\" value=\"%s\">\n",
 1607: 	    q_idx+1,sa_p->a_str);
 1608:     append_qtext(buf);
 1609:     sprintf(buf," <b>Last Answer:</b> %s\n",sa_p->a_str);
 1610:     append_qtext(buf);
 1611:   } else {
 1612:     while(sa_p) {
 1613:       sprintf(buf,"<input type=\"hidden\" name=\"LAST%02d,%02d\" value=\"%s\">\n",
 1614: 	      q_idx+1,sa_p->a_idx,sa_p->a_str);
 1615:       append_qtext(buf);
 1616:       sprintf(buf," <b>Last Answer %d:</b> %s\n",sa_p->a_idx,sa_p->a_str);
 1617:       append_qtext(buf);
 1618:       sa_p=sa_p->a_next;
 1619:     }
 1620:   }
 1621: }
 1622: 
 1623: void preserve_last_answer(int q_idx,int print)
 1624: {
 1625:   char       buf[MAX_BUFFER_SIZE];  
 1626:   StudentAnswer_t  *sa_p;
 1627: #ifdef CGI_DBUG
 1628:   fprintf(g_cgi,"Enter preserve_last_answer() [%d]\n",q_idx); fflush(g_cgi);
 1629: #endif /* CGI_DBUG */
 1630:   if(g_stu_ans_pp[q_idx+1] != NULL) {
 1631:     sa_p=g_stu_ans_pp[q_idx+1];
 1632:   } else {
 1633:     if (g_last_ans_pp[q_idx+1] != NULL) {
 1634:       sa_p=g_last_ans_pp[q_idx+1];
 1635:     } else {
 1636:       return;
 1637:     }
 1638:   }
 1639:   if (sa_p->a_next == NULL) {
 1640:     sprintf(buf,"<input type=\"hidden\" name=\"LAST%02d\" value=\"%s\">\n",
 1641: 	    q_idx+1,sa_p->a_str);
 1642:     if (print) printf(buf); else append_qtext(buf);
 1643:   } else {
 1644:     while(sa_p) {
 1645:       sprintf(buf,"<input type=\"hidden\" name=\"LAST%02d,%02d\" value=\"%s\">\n",
 1646: 	      q_idx+1,sa_p->a_idx,sa_p->a_str);
 1647:       if (print) printf(buf); else append_qtext(buf);
 1648:       sa_p=sa_p->a_next;
 1649:     }
 1650:   }
 1651: }
 1652: 
 1653: void display_last_subjective(int q_idx)
 1654: {
 1655:   char      *buf;
 1656:   char      *answer;
 1657: #ifdef CGI_DBUG
 1658:   fprintf(g_cgi,"Enter display_last_subjective() [%d]\n",q_idx); fflush(g_cgi);
 1659: #endif /* CGI_DBUG */
 1660:   answer=capa_get_subjective(g_login_set,q_idx+1,g_student_number);
 1661:   if (answer==NULL) return;
 1662: #ifdef CGI_DBUG
 1663:   fprintf(g_cgi,"Found answer %s\n",answer); fflush(g_cgi);
 1664: #endif /* CGI_DBUG */
 1665:   buf=capa_malloc(MAX_BUFFER_SIZE+strlen(answer),1);
 1666:   /* don't need to stick in a last since we always get it from the files */
 1667:   /*  sprintf(buf,"<input type=\"hidden\" name=\"LAST%02d\" value=\"%s\">\n",q_idx+1,answer);*/
 1668:   append_qtext(buf);
 1669:   append_qtext("<b>Current Submission:</b><br>\n");
 1670:   append_qtext("<TABLE BORDER=1 CELLSPACING=0>\n<TR><TD>\n");
 1671:   append_qtext("<PRE>");
 1672:   append_qtext(answer);
 1673:   append_qtext("</PRE>");
 1674:   append_qtext("</TD></TR></TABLE>\n");
 1675:   capa_mfree(buf);
 1676:   capa_mfree(answer);
 1677: }
 1678: 
 1679: void create_answer_area(Problem_t *p,int q_idx) 
 1680: {
 1681:   int ii=0;
 1682:   char       buf[MAX_BUFFER_SIZE];  
 1683:   AnswerInfo_t *ai;
 1684: #ifdef CGI_DBUG
 1685:   fprintf(g_cgi,"Enter create_answer_area() [%d]\n",q_idx); fflush(g_cgi);
 1686: #endif /* CGI_DBUG */
 1687: 
 1688:   if ( p->ans_type==ANSWER_IS_SUBJECTIVE ) {
 1689:     display_last_subjective(q_idx);
 1690:   }
 1691:   if ( p->show_ans_box ) { 
 1692:     if ( p->ans_op == ANS_AND ) {
 1693:       if (p->ans_type == ANSWER_IS_FORMULA) {
 1694: 	/* first answer is stored in p, the rest are linked off of p->ans_list */
 1695: 	sprintf(buf,"<p><B>Answer %d of %d:</B><input size=80 name=\"INPUT%02d,%02d\" value=\"\">\n",ii+1,p->ans_cnt,q_idx+1,ii+1);
 1696:       } else {
 1697: 	sprintf(buf,"<p><B>Answer %d of %d:</B><input name=\"INPUT%02d,%02d\" value=\"\">\n",ii+1,p->ans_cnt,q_idx+1,ii+1);
 1698:       }
 1699:       append_qtext(buf);
 1700:       for(ii=1, ai=p->ans_list;ii<p->ans_cnt;ai=ai->ans_next,ii++) {
 1701: 	if (ai->ans_type == ANSWER_IS_FORMULA) {
 1702: 	  sprintf(buf,"<p><B>Answer %d of %d:</B><input size=80 name=\"INPUT%02d,%02d\" value=\"\">\n",ii+1,p->ans_cnt,q_idx+1,ii+1);
 1703: 	} else {
 1704: 	  sprintf(buf,"<p><B>Answer %d of %d:</B><input name=\"INPUT%02d,%02d\" value=\"\">\n",ii+1,p->ans_cnt,q_idx+1,ii+1);
 1705: 	}
 1706: 	append_qtext(buf);
 1707:       }
 1708:     } else { /* single answer, or /OR answers, or subjective answer */
 1709:       if (p->ans_type == ANSWER_IS_SUBJECTIVE ) {
 1710: 	sprintf(buf,"<p><B>Answer:</B><br><TEXTAREA name=\"INPUT%02d\" rows=\"15\" cols=\"80\"></TEXTAREA>\n",q_idx+1);
 1711:       } else {
 1712: 	if (p->ans_type == ANSWER_IS_FORMULA) {
 1713: 	  sprintf(buf,"<p><B>Answer:</B><input size=80 name=\"INPUT%02d\" value=\"\">\n",q_idx+1);
 1714: 	} else {
 1715: 	  sprintf(buf,"<p><B>Answer:</B><input name=\"INPUT%02d\" value=\"\">\n",q_idx+1);
 1716: 	}
 1717:       }
 1718:       append_qtext(buf);
 1719:     }
 1720:   }
 1721:   append_qtext("<input type=\"submit\" value=\"Submit All Answers\" >\n");
 1722:   if ( p->ans_type!=ANSWER_IS_SUBJECTIVE ) {
 1723:     display_last_answer(q_idx);
 1724:   }
 1725: }
 1726: 
 1727: void
 1728: print_response(char pcr,char u_db,int q_idx,Problem_t *p)
 1729: {
 1730: int   a_tpe;
 1731: char *c_ans,*response,*answered="Answered",*nycorrect="Not yet correct";
 1732: int   t_tpe;
 1733: double tol;
 1734: int    sig_l;
 1735: int    sig_u;
 1736: char  *a_fmt, *c_answer_str;
 1737: int    tries;
 1738: 
 1739:     char       buf[MAX_BUFFER_SIZE];
 1740: 
 1741:  a_tpe = p->ans_type;
 1742:  c_ans = p->answer;
 1743:  t_tpe = p->tol_type;
 1744:  tol   = p->tolerance;
 1745:  sig_l = p->sig_lbound;
 1746:  sig_u = p->sig_ubound;
 1747:  a_fmt = p->ans_fmt;
 1748:  tries = p->tries;
 1749:  response=nycorrect;
 1750: 
 1751: #ifdef CGI_DBUG
 1752:   fprintf(g_cgi,"Enter print_response() [%c]\n",u_db); fflush(g_cgi);
 1753: #endif /* CGI_DBUG */
 1754:   if( pcr == '0' || a_tpe==ANSWER_IS_SUBJECTIVE ) { /* not hand-graded question */
 1755:      switch(u_db) {  /* this is from the user record */
 1756:        case 'Y':
 1757:                c_answer_str = answers_string(ANSWER_STRING_MODE, p);
 1758:                sprintf(buf,"<p><tt>Correct, computer gets: %s</tt>\n", c_answer_str);
 1759:                append_qtext(buf);
 1760:                capa_mfree((char *)c_answer_str);
 1761:                break;
 1762:        case 'y':
 1763:                append_qtext("<p><tt>Hand-graded Correct</tt>\n");
 1764:                break;
 1765:        case '-':
 1766:                if(g_stu_ans_pp[q_idx+1] == NULL ) {
 1767: 		 create_answer_area(p,q_idx);
 1768: 	       } else {
 1769:                  check_user_ans(q_idx,p);
 1770:                }
 1771:                break;
 1772:        case 'E':
 1773:        case 'e': append_qtext("<p><tt>Excused</tt>\n");               break;
 1774:        case 'n': append_qtext("<p><tt>Hand-graded Incorrect</tt>\n"); break;
 1775:        case '0': case '1': case '2': case '3': case '4': 
 1776:        case '5': case '6': case '7': case '8': case '9':
 1777: 	 response=answered;
 1778:        case 'N':
 1779:                if(g_stu_ans_pp[q_idx+1] == NULL ) {
 1780: 		 if( g_tried[q_idx] < tries) {
 1781: 		   create_answer_area(p,q_idx);
 1782: 		   if( tries - g_tried[q_idx] == 1) {
 1783: 		     sprintf(buf,"<br><tt>%s, ONE try left!!</tt>\n",response);
 1784: 		   }else{
 1785: 		     sprintf(buf,"<br><tt>%s, tries %d/%d</tt>\n",response,
 1786: 			     g_tried[q_idx],tries);
 1787: 		   }  
 1788: 		   append_qtext(buf);
 1789: 		 }else{
 1790: 		   if (p->ans_type==ANSWER_IS_SUBJECTIVE)
 1791: 		     display_last_answer(q_idx);
 1792: 		   else
 1793: 		     display_last_subjective(q_idx);
 1794: 		   append_qtext("<br><tt>No more tries.</tt>\n");
 1795: 		 } 
 1796:                } else { /* answering this question */
 1797: 		 if( g_tried[q_idx] < tries) {
 1798: 		   check_user_ans(q_idx,p);
 1799: 		 } else {
 1800: 		   if (p->ans_type==ANSWER_IS_SUBJECTIVE)
 1801: 		     display_last_answer(q_idx);
 1802: 		   else
 1803: 		     display_last_subjective(q_idx);
 1804: 		   append_qtext("<br><tt>No more tries.</tt>\n");
 1805: 		 }
 1806: 	       }
 1807:                break;
 1808:      }
 1809:    } else {
 1810:      append_qtext("<p><tt>Question to be Graded Manually.</tt>\n");
 1811:      
 1812:    }
 1813: 
 1814: }
 1815: 
 1816: void
 1817: print_inhibited_response(char pcr,char u_db,int q_idx,Problem_t *p)
 1818: {
 1819: int   a_tpe;
 1820: char *c_ans;
 1821: int   t_tpe;
 1822: double tol;
 1823: int    sig_l;
 1824: int    sig_u;
 1825: char  *a_fmt;
 1826: int    tries;
 1827: char       buf[MAX_BUFFER_SIZE];
 1828: 
 1829:  a_tpe = p->ans_type;
 1830:  c_ans = p->answer;
 1831:  t_tpe = p->tol_type;
 1832:  tol   = p->tolerance;
 1833:  sig_l = p->sig_lbound;
 1834:  sig_u = p->sig_ubound;
 1835:  a_fmt = p->ans_fmt;
 1836:  tries = p->tries;
 1837: 
 1838: #ifdef CGI_DBUG
 1839:   fprintf(g_cgi,"Enter print_inhibited_response() [%c]\n",u_db); fflush(g_cgi);
 1840: #endif /* CGI_DBUG */
 1841: 
 1842:   if( pcr == '0' || a_tpe==ANSWER_IS_SUBJECTIVE ) { /* not hand-graded question */
 1843:      switch(u_db) {  /* this is from the user record */
 1844:        case '-': 
 1845:                if(g_stu_ans_pp[q_idx+1] == NULL ) {
 1846: 		 create_answer_area(p,q_idx);
 1847:                } else {
 1848:                  check_inhibited_user_ans(q_idx,p);
 1849:                }
 1850:                break;
 1851:        case 'Y': case 'y':
 1852:        case 'E': case 'e': 
 1853:        case 'n': case 'N': 
 1854:        case '0': case '1': case '2': case '3': case '4': 
 1855:        case '5': case '6': case '7': case '8': case '9':
 1856:                if(g_stu_ans_pp[q_idx+1] == NULL ) {
 1857: 		 if( g_tried[q_idx] < tries) {
 1858: 		   create_answer_area(p,q_idx);	
 1859: 		   if( tries - g_tried[q_idx] == 1) {
 1860: 		     append_qtext("<br><tt>Answered, ONE try left!!</tt>\n");
 1861: 		   }else{
 1862: 		     sprintf(buf,"<br><tt>Answered, tries %d/%d</tt>\n",g_tried[q_idx],tries);
 1863: 		     append_qtext(buf);
 1864: 		   }  
 1865: 		 }else{
 1866: 		   if (p->ans_type==ANSWER_IS_SUBJECTIVE)
 1867: 		     display_last_answer(q_idx);
 1868: 		   else
 1869: 		     display_last_subjective(q_idx);
 1870: 		   append_qtext("<br><tt>Answered,No more tries.</tt>\n");
 1871: 		 } 
 1872: 	       } else { /* answering this question */
 1873: 		 if( g_tried[q_idx] < tries) {
 1874: 		   check_inhibited_user_ans(q_idx,p);
 1875: 		 } else {
 1876: 		   if (p->ans_type==ANSWER_IS_SUBJECTIVE)
 1877: 		     display_last_answer(q_idx);
 1878: 		   else
 1879: 		     display_last_subjective(q_idx);
 1880: 		   append_qtext("<br><tt>Answered, No more tries.</tt>\n");
 1881: 		 }
 1882:                }
 1883:                break;
 1884:      }
 1885:    } else {
 1886:      append_qtext("<p><tt>Question to be Graded Manually.</tt>\n"); 
 1887:    }
 1888: }
 1889: 
 1890: /* returns a -1 if there were not enough answers, otherwise the number of responses
 1891:    for the question is returned
 1892:    !!!!!AS A SIDEEFFECT IT ALSO CROPS ANSWERS TO ANSWER_STRING_LENG!!!!!!!
 1893: */
 1894: int gather_answers(char ***ans,int q_idx,Problem_t *p)
 1895: {
 1896:   int cnt;
 1897:   if(p->ans_op==ANS_AND) {
 1898:     int i; StudentAnswer_t *sa_p;
 1899:     *ans=(char**)capa_malloc(p->ans_cnt,1);
 1900:     sa_p= g_stu_ans_pp[q_idx+1];
 1901:     for(i=0;((i<p->ans_cnt)&&(sa_p));i++){
 1902:       ans[0][i]=sa_p->a_str;
 1903:       if ((strlen(ans[0][i])+1) > ANSWER_STRING_LENG) ans[0][i][ANSWER_STRING_LENG]='\0';
 1904:       sa_p=sa_p->a_next;
 1905:     }
 1906:     cnt=p->ans_cnt;
 1907:     if (i<p->ans_cnt) return -1;
 1908:   } else {
 1909:     *ans=(char**)capa_malloc(p->ans_cnt,1);
 1910:     ans[0][0]=g_stu_ans_pp[q_idx+1]->a_str;
 1911:     if ((strlen(ans[0][0])+1) > ANSWER_STRING_LENG) ans[0][0][ANSWER_STRING_LENG]='\0';
 1912:     cnt=1;
 1913:   }
 1914:   return cnt;
 1915: }
 1916: 
 1917: /*logging user's answer when it is passed due.*/
 1918: void
 1919: log_user_ans(int q_idx,Problem_t *p)
 1920: {
 1921:   char **ans;
 1922:   int cnt;
 1923:   if (p->ans_type==ANSWER_IS_SUBJECTIVE) {
 1924:       /*capa_set_subjective(g_login_set,q_idx+1,g_student_number,
 1925: 	g_stu_ans_pp[q_idx+1]->a_str);*/
 1926:   } else {
 1927:     if (-1 != (cnt=gather_answers(&ans,q_idx,p))) {
 1928:       switch( capa_check_answers(p,ans,cnt) ) {
 1929:         case  EXACT_ANS:  g_log_string[q_idx]='Y'; break;
 1930:         case  APPROX_ANS: g_log_string[q_idx]='Y'; break;
 1931:         case  SIG_FAIL:   g_log_string[q_idx]='S'; break;
 1932:         case  UNIT_FAIL:  g_log_string[q_idx]='U'; break;
 1933:         case  UNIT_NOTNEEDED:  g_log_string[q_idx]='U'; break;
 1934:         case  NO_UNIT:    g_log_string[q_idx]='u'; break;
 1935:         case  BAD_FORMULA:  g_log_string[q_idx]='F'; break;
 1936:         case  INCORRECT:  g_log_string[q_idx]='N'; break;
 1937:       }
 1938:     }
 1939:   }
 1940: }
 1941: 
 1942: void submit_subjective(int q_idx,Problem_t *p)
 1943: {
 1944:   char buf[MAX_BUFFER_SIZE];
 1945:   if (capa_set_subjective(g_login_set,q_idx+1,g_student_number,
 1946: 			  g_stu_ans_pp[q_idx+1]->a_str)<0){
 1947:     sprintf(buf,"<p><tt>Falied to record last submission.</tt><br>\n");
 1948:     g_tried[q_idx]--;
 1949:   } else {
 1950:     sprintf(buf,"<p><tt>Current submission recorded.</tt><br>\n");
 1951:     g_new_answerdb[q_idx] = '0';
 1952:     g_log_string[q_idx]='A';
 1953:   }
 1954:   append_qtext(buf);
 1955:   if (g_tried[q_idx]<p->tries) {
 1956:     create_answer_area(p,q_idx);
 1957:     if( p->tries - g_tried[q_idx] == 1) {
 1958:       append_qtext("<br><tt>ONE try left</tt>\n");
 1959:     }else{
 1960:       sprintf(buf,"<br><tt>tries %d/%d</tt>\n",g_tried[q_idx],p->tries);
 1961:       append_qtext(buf);
 1962:     }  
 1963:   }else{
 1964:     display_last_answer(q_idx);
 1965:     append_qtext("<br><tt>No more tries.</tt>\n");
 1966:   } 
 1967: }
 1968: 
 1969: void
 1970: check_user_ans(int q_idx,Problem_t *p)
 1971: {
 1972: int a_tpe,cnt;
 1973: char *c_ans,**ans;
 1974: int   t_tpe;
 1975: double tol;
 1976: int    sig_l;
 1977: int    sig_u;
 1978: char  *a_fmt;
 1979: int    tries;
 1980:   char       buf[MAX_BUFFER_SIZE];
 1981:   
 1982:   a_tpe = p->ans_type;
 1983:   t_tpe = p->tol_type;
 1984:   tol   = p->tolerance;
 1985:   sig_l = p->sig_lbound;
 1986:   sig_u = p->sig_ubound;
 1987:   a_fmt = p->ans_fmt;
 1988:   tries = p->tries;
 1989: 
 1990: #ifdef CGI_DBUG
 1991:   fprintf(g_cgi,"Enter check_user_ans() anstype=%d\n",a_tpe); fflush(g_cgi);
 1992: #endif /* CGI_DBUG */
 1993: 
 1994:   g_tried[q_idx]++;
 1995: 
 1996: #ifdef CGI_DBUG
 1997:   fprintf(g_cgi,"Call capa_check_answer() with [%s]\n",g_stu_ans_pp[q_idx+1]->a_str); fflush(g_cgi);
 1998: #endif /* CGI_DBUG */
 1999:   if (a_tpe==ANSWER_IS_SUBJECTIVE) {
 2000:     submit_subjective(q_idx,p);
 2001:     return;
 2002:   }
 2003:   
 2004:   cnt=gather_answers(&ans,q_idx,p);
 2005:   if (cnt == -1) {
 2006:     g_tried[q_idx]--;
 2007:     create_answer_area(p,q_idx);
 2008:     if( (tries - g_tried[q_idx]) == 1 ) {
 2009:       append_qtext("<br><tt>Not all answers submitted, ONE try left!!</tt>\n");
 2010:     }else{
 2011:       sprintf(buf,"<br><tt>Not all answers submitted, tries %d/%d.</tt>\n",
 2012: 	      g_tried[q_idx],tries);
 2013:       append_qtext(buf);
 2014:     }
 2015:     return;
 2016:   }
 2017: 
 2018:   switch( capa_check_answers(p,ans,cnt) ) {
 2019:     case  EXACT_ANS:    
 2020:     case  APPROX_ANS: 
 2021:                    c_ans=answers_string(ANSWER_STRING_MODE, p);
 2022:                    sprintf(buf,"<p><tt>Yes, Computer gets: %s</tt>\n", c_ans);
 2023:                    append_qtext(buf);
 2024:                    g_new_answerdb[q_idx] = 'Y';
 2025:                    g_log_string[q_idx]='Y';
 2026: 		   capa_mfree(c_ans);
 2027: 		   break;
 2028:     case  SIG_FAIL:
 2029:                    create_answer_area(p,q_idx);
 2030: 		   g_tried[q_idx]--;  /* don't count as a try */
 2031: 		   sprintf(buf,"<br><tt>Please adjust significant figures, tries %d/%d.</tt>\n",g_tried[q_idx],tries);
 2032: 		   append_qtext(buf);
 2033: 		   g_new_answerdb[q_idx] = 'N';
 2034:                    g_log_string[q_idx]='S';
 2035:                    break;
 2036:     case  UNIT_FAIL:
 2037:                    create_answer_area(p,q_idx);
 2038:                    g_tried[q_idx]--;  /* don't count as a try */
 2039: 		   sprintf(buf,"<br><tt>Units incorrect, tries %d/%d.</tt>\n",g_tried[q_idx],tries);
 2040: 		   append_qtext(buf);
 2041: 		   g_new_answerdb[q_idx] = 'N';
 2042:                    g_log_string[q_idx]='U';
 2043:                    break;
 2044:     case  UNIT_NOTNEEDED:
 2045:                    create_answer_area(p,q_idx);
 2046:                    g_tried[q_idx]--;  /* don't count as a try */
 2047:                    if(tries > 0) {
 2048:                      sprintf(buf,"<br><tt>Only a number required, tries %d/%d.</tt>\n",g_tried[q_idx],tries);
 2049:                      append_qtext(buf);
 2050:                    }
 2051:                    g_new_answerdb[q_idx] = 'N';
 2052:                    g_log_string[q_idx]='U';
 2053:                    break;
 2054:     case  NO_UNIT: 
 2055:                    create_answer_area(p,q_idx);
 2056:                    g_tried[q_idx]--;  /* don't count as a try */
 2057: 		   sprintf(buf,"<br><tt>Units required, tries %d/%d.</tt>\n",g_tried[q_idx],tries);
 2058: 		   append_qtext(buf);
 2059: 		   g_new_answerdb[q_idx] = 'N';
 2060:                    g_log_string[q_idx]='u';
 2061:                    break;
 2062:     case  BAD_FORMULA: 
 2063:                    create_answer_area(p,q_idx);
 2064:                    g_tried[q_idx]--;  /* don't count as a try */
 2065: 		   sprintf(buf,"<br><tt>Unable to understand formula, tries %d/%d.</tt>\n",g_tried[q_idx],tries);
 2066: 		   append_qtext(buf);
 2067: 		   g_new_answerdb[q_idx] = 'N';
 2068:                    g_log_string[q_idx]='F';
 2069:                    break;
 2070:     case  INCORRECT:
 2071:                    if( g_tried[q_idx] < tries ) {
 2072: 		     create_answer_area(p,q_idx);
 2073: 		     if( (tries - g_tried[q_idx]) == 1 ) {
 2074: 		       append_qtext("<br><tt>Incorrect, ONE try left!!</tt>\n");
 2075: 		     }else{
 2076: 		       sprintf(buf,"<br><tt>Incorrect, tries %d/%d.</tt>\n",g_tried[q_idx],tries);
 2077: 		       append_qtext(buf);
 2078: 		     }
 2079: 		   } else {
 2080: 		     display_last_answer(q_idx);
 2081: 		     append_qtext("<br><tt>Incorrect, no more tries.</tt>\n");
 2082: 		   }
 2083:                    g_new_answerdb[q_idx] = 'N';
 2084:                    g_log_string[q_idx]='N';
 2085:                    break;
 2086:   }
 2087: }
 2088: 
 2089: void
 2090: check_inhibited_user_ans(int q_idx,Problem_t *p)
 2091: {
 2092: int a_tpe,cnt;
 2093: char *c_ans,**ans;
 2094: int   t_tpe;
 2095: double tol;
 2096: int    sig_l;
 2097: int    sig_u;
 2098: char  *a_fmt;
 2099: int    tries;
 2100:   char       buf[MAX_BUFFER_SIZE];
 2101:   
 2102:   a_tpe = p->ans_type;
 2103:   c_ans = p->answer;
 2104:   t_tpe = p->tol_type;
 2105:   tol   = p->tolerance;
 2106:   sig_l = p->sig_lbound;
 2107:   sig_u = p->sig_ubound;
 2108:   a_fmt = p->ans_fmt;
 2109:   tries = p->tries;
 2110:   
 2111: #ifdef CGI_DBUG
 2112:   fprintf(g_cgi,"Enter check_inhibited_user_ans() anstype=%d\n",a_tpe); fflush(g_cgi);
 2113: #endif /* CGI_DBUG */
 2114: 
 2115:   g_tried[q_idx]++;
 2116: 
 2117: #ifdef CGI_DBUG
 2118:   fprintf(g_cgi,"Call capa_check_answer() with [%s]\n",g_stu_ans_pp[q_idx+1]->a_str); 
 2119:   fflush(g_cgi);
 2120: #endif /* CGI_DBUG */
 2121:   if (a_tpe==ANSWER_IS_SUBJECTIVE) {
 2122:     submit_subjective(q_idx,p);
 2123:     return;
 2124:   }
 2125: 
 2126:   cnt=gather_answers(&ans,q_idx,p);
 2127:   if (cnt == -1) {
 2128:     g_tried[q_idx]--;
 2129:     create_answer_area(p,q_idx);
 2130:     if( (tries - g_tried[q_idx]) == 1 ) {
 2131:       append_qtext("<br><tt>Not all answers submitted, ONE try left!!</tt>\n");
 2132:     }else{
 2133:       sprintf(buf,"<br><tt>Not all answers submitted, tries %d/%d.</tt>\n",
 2134: 	      g_tried[q_idx],tries);
 2135:       append_qtext(buf);
 2136:     }
 2137:     return;
 2138:   }
 2139: 
 2140:   switch( capa_check_answers(p,ans,cnt) ) {
 2141:     case  EXACT_ANS:
 2142:     case  APPROX_ANS: 
 2143:                    g_new_answerdb[q_idx] = 'Y';
 2144:                    g_log_string[q_idx]='Y';
 2145:                    break;
 2146:     case  SIG_FAIL:
 2147:                    g_new_answerdb[q_idx] = 'N';
 2148:                    g_log_string[q_idx]='S';
 2149:                    break;
 2150:     case  UNIT_FAIL:
 2151:                    g_new_answerdb[q_idx] = 'N';
 2152:                    g_log_string[q_idx]='U';
 2153:                    break;
 2154:     case  UNIT_NOTNEEDED:
 2155:                    g_new_answerdb[q_idx] = 'N';
 2156:                    g_log_string[q_idx]='U';
 2157:                    break;
 2158:     case  NO_UNIT:
 2159:                    g_new_answerdb[q_idx] = 'N';
 2160:                    g_log_string[q_idx]='u';
 2161:                    break;
 2162:     case  BAD_FORMULA:
 2163:                    g_new_answerdb[q_idx] = 'N';
 2164:                    g_log_string[q_idx]='F';
 2165:                    break;
 2166:     case  INCORRECT:
 2167:                    g_new_answerdb[q_idx] = 'N';
 2168:                    g_log_string[q_idx]='N';
 2169:                    break;
 2170:   }
 2171: 
 2172:   if( g_tried[q_idx] < tries ) {
 2173:     create_answer_area(p,q_idx);
 2174:     if( (tries - g_tried[q_idx]) == 1 ) {
 2175:       append_qtext("<br><tt>Answered, ONE try left!!</tt>\n");
 2176:     }else{
 2177:       sprintf(buf,"<br><tt>Answered, tries %d/%d.</tt>\n",g_tried[q_idx],tries);
 2178:       append_qtext(buf);
 2179:     }
 2180:   } else {
 2181:     display_last_answer(q_idx);
 2182:     append_qtext("<br><tt>Answered, no more tries.</tt>\n");
 2183:   }
 2184: }
 2185: 
 2186: void                                     /* RETURNS: (nothing)          */
 2187: print_summary(class_dir,class,student_number,pin,set)
 2188: char *class_dir;char *class;char *student_number;int pin;int set;
 2189: {                                       /* LOCAL VARIABLES:            */
 2190:   int      set_idx,                     /*    Set counter              */
 2191:            i,                           /*    Question counter         */
 2192:            set_score,                   /*    Score on a set           */
 2193:            term_score=0,                /*    Total points received    */
 2194:            term_valid=0,                /*    Total points possible    */
 2195:            result,
 2196:            tot_num_sets=0;
 2197:   T_entry  entry;                       /*    Database entry for a set */
 2198:   char     buf[MAX_BUFFER_SIZE]; /* Output line buffer  */
 2199:   char     buf2[MAX_BUFFER_SIZE]; /* Output line buffer  */
 2200:   T_header header;                      /*    Problem set header       */
 2201:   int      question_cnt,valid_wgt, rate,configResult,
 2202:     status_line_length=DEFAULT_STATUS_LINE_LENGTH,row;
 2203:   char     class_fullpath[ONE_K],*serverName;
 2204: 
 2205:   serverName=getenv("SERVER_NAME");
 2206:   if (!serverName) {
 2207:     fprintf(stdout,"Enviroment variable SERVER_NAME not set.\n");
 2208:     fprintf(stdout,"Unable to complete actions.\n");
 2209:     return;
 2210:   }
 2211:   printf("<!--print_summary-->");
 2212:   sprintf(class_fullpath,"%s/%s",class_dir,class);
 2213:   chdir(class_fullpath);
 2214:   configResult=read_capa_config("web_status_line_length",buf);
 2215:   if (configResult != 0 && configResult != -1 ) {
 2216:     if (sscanf(buf,"%d",&status_line_length)==0) {
 2217:       status_line_length=DEFAULT_STATUS_LINE_LENGTH;
 2218:     }
 2219:   } else {
 2220:     status_line_length=DEFAULT_STATUS_LINE_LENGTH;
 2221:   }
 2222:   
 2223:   printf("<TABLE>\n<TR><TD></TD>\n");
 2224:   for(i=0;i<status_line_length;i++) {
 2225:     printf("<TD align=center valign=bottom>%d</TD>\n",i+1);
 2226:   }
 2227:   printf("</TR>");
 2228: 
 2229:   for (set_idx=1; set_idx<=set; set_idx++) {
 2230:     g_inhibit_response=capa_check_option(OPTION_INHIBIT_RESPONSE,set_idx,
 2231: 					 g_student_data.s_sec);
 2232:     if (g_inhibit_response > 0) {
 2233:       printf("<!-- Set %d is inhibited -->\n",set_idx);
 2234:       continue;
 2235:     }
 2236:     if ( capa_check_date(CHECK_OPEN_DATE,g_student_number,
 2237: 			     g_student_data.s_sec,set_idx) < 0 ){
 2238:       printf("<!-- Set %d is not open -->\n",set_idx);
 2239:       continue;
 2240:     }
 2241: 
 2242:     if (capa_get_header(&header,set_idx))  return;
 2243:     tot_num_sets++;
 2244:     capa_get_entry(&entry,student_number,set_idx);
 2245:     sscanf(header.num_questions,"%d", &(question_cnt) );
 2246:     valid_wgt = 0; set_score = 0;
 2247:     header.weight[question_cnt] = '\0';
 2248:     header.partial_credit[question_cnt] = '\0';
 2249:     for (i=0; i<question_cnt; i++) {
 2250:       valid_wgt +=  (header.weight[i] - '0');
 2251:       if((entry.answers[i]=='Y') || (entry.answers[i]=='y'))  
 2252: 	set_score += (header.weight[i]-'0');
 2253:       if((entry.answers[i]=='E') || (entry.answers[i]=='e'))  
 2254: 	valid_wgt -= (header.weight[i] - '0');
 2255:       if((entry.answers[i]>='0') && (entry.answers[i]<='9'))  
 2256: 	set_score += (entry.answers[i] - '0');
 2257:     }
 2258:     term_valid += valid_wgt;
 2259:     term_score += set_score;
 2260: 
 2261:     if( valid_wgt != 0 ) {
 2262:       rate = 100*set_score / valid_wgt;
 2263:       printf("<TR><TD nowrap align=center valign=bottom>set <B>%d</B>, %d/%d(%d %%)  </TD>",set_idx,set_score,valid_wgt,rate);
 2264:     } else {
 2265:       printf("<TR><TD nowrap align=center valign=bottom>set <B>%d</B>,   0/0(0 %%)   </TD>",set_idx);
 2266:     }
 2267:     for(row=0;row<=(question_cnt/status_line_length);row++) {
 2268:       for(i=(row*status_line_length);
 2269: 	  ((i<question_cnt)&&(i<((row+1)*status_line_length))); i++) {
 2270: 	if (i != 0 && (!(i%status_line_length))) { printf("</TR><TD></TD>"); }
 2271: 	printf("<TD align=center valign=bottom><tt>%c</tt></TD>\n",entry.answers[i]);
 2272:       }
 2273:       printf("</TR>\n<TR><TD></TD>");
 2274:       for(i=(row*status_line_length);
 2275: 	  ((i<question_cnt)&&(i<((row+1)*status_line_length))); i++) {
 2276: 	if (i != 0 && (!(i%status_line_length))) { printf("</TR><TD></TD>"); }
 2277: 	printf("<TD align=center valign=bottom><tt>%c</tt></TD>\n",header.weight[i]);
 2278:       }
 2279:     }
 2280:     printf("</TR>");
 2281:     capa_mfree(header.weight);
 2282:     capa_mfree(header.partial_credit);
 2283:   }
 2284:   printf("\n</TABLE>\n<hr>\n");
 2285:   /* SHOW TOTALS */
 2286:   /* if capalogin_show_summary_score is set to none don't show it */
 2287:   if (term_valid > 0) {
 2288:     sprintf(buf,"%d sets, total = %3d/%3d (%d%%)\n", tot_num_sets, term_score, term_valid, 100*term_score/term_valid);
 2289:   } else {
 2290:     sprintf(buf,"%d sets, total = %3d/%3d\n", tot_num_sets, term_score, term_valid);
 2291:   }
 2292:   result=read_capa_config("capalogin_show_summary_score",buf2);
 2293:   if (result != 0 && result != -1) {
 2294:     if (strcasecmp(buf2,"none")==0) {
 2295:     } else {
 2296:       printf("%s",buf);
 2297:     }
 2298:   } else {
 2299:     printf("%s",buf);
 2300:   }
 2301: 
 2302:   printf("<TABLE cellpadding=0 cellspacing=0 border=0>\n<TR><TD>");
 2303:   printf("<form method=\"post\" ");
 2304:   sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,g_cgibin_path,g_cowner);
 2305:   printf("%s\n", buf);
 2306:   printf("<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",g_class_name);
 2307:   printf("<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",g_student_number);
 2308:   printf("<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",g_entered_pin);
 2309:   printf("<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_CHECKIN);
 2310:   printf("<input type=\"submit\" value=\"Main menu\" ></form></TD>\n");
 2311:   printf("<TD><form method=\"get\" action=\"http://%s/CAPA/class.html\">",serverName); 
 2312:   printf("<input type=\"button\" value=\"Exit\" onclick=\"window.close()\"></form></TD>");
 2313:   printf("\n</TABLE>\n");
 2314: }
 2315: 
 2316: 
 2317: void
 2318: process_mode(int mode) {
 2319: 
 2320: #ifdef CGI_DBUG
 2321:   fprintf(g_cgi,"entered process_mode[%d]\n",mode); fflush(g_cgi);
 2322: #endif /* CGI_DBUG */
 2323:   g_qchar_cnt=g_schar_cnt=0;
 2324:   g_qsize=TEXT_BUF_SIZE*sizeof(char);
 2325:   g_ssize=STATUS_BUF_SIZE*sizeof(char);
 2326:   g_question_txt=capa_malloc(TEXT_BUF_SIZE,sizeof(char));
 2327:   g_status_txt  =capa_malloc(STATUS_BUF_SIZE,sizeof(char));
 2328: #ifdef CGI_DBUG
 2329:   fprintf(g_cgi,"alloced everything\n"); fflush(g_cgi);
 2330: #endif /* CGI_DBUG */
 2331:   if( mode == VIEW_PREVIOUS_MODE ) {
 2332:     print_quizz(g_cpath,g_cowner,g_class_name,g_student_number, g_entered_pin, g_vset,mode); 
 2333:   } else if( mode == TRY_SET_MODE ) {
 2334:     print_quizz(g_cpath,g_cowner,g_class_name,g_student_number, g_entered_pin, g_login_set,mode);
 2335:   } else {
 2336:     print_quizz(g_cpath,g_cowner,g_class_name,g_student_number,g_entered_pin,g_login_set,CHECK_ANSWER_MODE);
 2337:   }
 2338:   g_status_txt[g_schar_cnt]=0;
 2339:   g_question_txt[g_qchar_cnt]=0;
 2340:   if( g_schar_cnt != 0 ) {
 2341:          fprintf(stdout,"%s",g_status_txt);
 2342: #ifdef CGI_DBUG
 2343:   fprintf(g_cgi,"print status [%s]\n",g_status_txt); fflush(g_cgi);
 2344: #endif /* CGI_DBUG */
 2345:   }
 2346:   if( g_qchar_cnt != 0) {
 2347:          fprintf(stdout,"%s",g_question_txt);
 2348: #ifdef CGI_DBUG
 2349:   fprintf(g_cgi,"print question [%s]\n",g_question_txt); fflush(g_cgi);
 2350: #endif /* CGI_DBUG */
 2351:   }
 2352:   if( g_schar_cnt != 0 ) {
 2353:          fprintf(stdout,"%s",g_status_txt);
 2354:   }
 2355:   fflush(stdout);
 2356:   capa_mfree(g_status_txt);
 2357:   capa_mfree(g_question_txt);
 2358: 
 2359: }
 2360: 
 2361: /*  mode could be exam summary, show or not show percentage */
 2362: /*                quiz summary, show or not show percentage */
 2363: void
 2364: process_summary(int mode)
 2365: {
 2366:   int   outcome;
 2367:   int   i, len;
 2368:   char *c_name;
 2369:   char  c_path[512];
 2370:   
 2371:   outcome = check_exam_quiz_path();
 2372:   if( (mode == M_EXAMSUMM) && (outcome & 1) ) {  /* exam summary */
 2373:     c_name = rindex(g_exam_path,'/');
 2374:     c_name++;
 2375:     i = strlen(c_name);
 2376:     len = strlen(g_exam_path) - i - 1;
 2377:     for(i=0;i<len;i++) {
 2378:       c_path[i]=g_exam_path[i];
 2379:     }
 2380:     c_path[len]=0;
 2381:     print_summary(c_path,c_name,g_student_number, g_entered_pin, g_exam_set);
 2382:   }
 2383:   if( (mode == M_QUIZSUMM) && (outcome & 2) ) {  /* quiz summary */
 2384:     c_name = rindex(g_quiz_path,'/');
 2385:     c_name++;
 2386:     i = strlen(c_name);
 2387:     len = strlen(g_quiz_path) - i - 1;
 2388:     for(i=0;i<len;i++) {
 2389:       c_path[i]=g_quiz_path[i];
 2390:     }
 2391:     c_path[len]=0;
 2392:     print_summary(c_path,c_name,g_student_number, g_entered_pin, g_quiz_set);
 2393:   }
 2394:   
 2395: }
 2396: 
 2397: /* ---------------- JAVA TScore.class page print out ----------------- */
 2398: void                                     /* RETURNS: (nothing)          */
 2399: print_termscore_page(class_dir,class,student_number,pin,set,out)
 2400: char *class_dir;char *class;char *student_number;int pin;int set; /* student login set */
 2401: FILE *out;
 2402: {                                       /* LOCAL VARIABLES:            */
 2403:   int      set_idx,                     /*    Set counter              */
 2404:            i,                           /*    Question counter         */
 2405:            set_score,                   /*    Score on a set           */
 2406:            term_score=0,                /*    Total points received    */
 2407:            term_valid=0;                /*    Total points possible    */
 2408:   T_entry  entry;                       /*    Database entry for a set */
 2409:   char     buf[MAX_BUFFER_SIZE]; /* Output line buffer  */
 2410:   T_header header;                      /*    Problem set header       */
 2411:   int      question_cnt,valid_wgt,configResult;
 2412:   char     class_fullpath[ONE_K],*serverName;
 2413:   int      hw_c, hw_r, qz_c, qz_r, fs, homework_count, quiz_count;
 2414:   float    hw_w, qz_w, ex_w, fe_w, pc_w;
 2415:   int      idx, entry_count, tmp_len;
 2416:   float    *S, *F;
 2417:   int      *X; /* array controlling whether to extrapolate scores */
 2418:   char     *capa_server;
 2419:   int      max_set[4], width=600,height=750; /* width and height of applet*/
 2420:   char     **c_path_pp;
 2421: 
 2422:   /*Unused Vars  
 2423:     char     buf2[MAX_BUFFER_SIZE]; 
 2424:     char *qz_p, *ex_p, *epc_p; 
 2425:     int      ex_c, epc_c, result;
 2426:     int  rate, status_line_length=DEFAULT_STATUS_LINE_LENGTH,row;
 2427:   */
 2428: 
 2429:   serverName=getenv("SERVER_NAME");
 2430:   if (!serverName) {
 2431:     fprintf(out,"Enviroment variable SERVER_NAME not set.\n");
 2432:     fprintf(out,"Unable to complete actions.\n");
 2433:     return;
 2434:   }
 2435: 
 2436:   sprintf(class_fullpath,"%s/%s",class_dir,class);
 2437:   chdir(class_fullpath);
 2438:   
 2439:   /*
 2440:      change the working director to the major homework directory and begin to
 2441:      read off the remaining path informations from this capa.config file 
 2442:      homework_path   = 
 2443:      quiz_path   = 
 2444:      exam_path   = 
 2445:      correction_path = 
 2446:      homework_weight   = 0.3
 2447:      quiz_weight       = 0.7
 2448:      exam_weight       = 0.3
 2449:      final_weight      = 0.35
 2450:      correction_weight = 0.3
 2451:      final_exam_set_number = 4
 2452:      homework_count    = 12
 2453:      quiz_count        = 24
 2454:      
 2455:   */
 2456:   
 2457:   configResult=read_capa_config("capa_server",buf);
 2458:   if (configResult != 0 && configResult != -1 ) {
 2459:     tmp_len = strlen(buf) + 1;
 2460:     capa_server =   (char *)capa_malloc( tmp_len, sizeof(char));
 2461:     sprintf(capa_server,"%s",buf);
 2462:   } else { /* if capa_server is not set then we won't do anything further */
 2463:     fprintf(out,"Parameter: capa_server in capa.config file are not properly set.\n");
 2464:     return ;
 2465:   }
 2466:   if( get_termscore_params(&hw_w,&qz_w,&ex_w,&fe_w,&pc_w,&homework_count,&quiz_count,&fs) == -1 ) {
 2467:     fprintf(out,"Parameters in capa.config file are not properly set.\n");
 2468:     fprintf(out," such as homework_weight, quiz_weight, exam_weight, final_weight, correction_weight.\n");
 2469:     
 2470:     return;
 2471:   }
 2472: 
 2473:   get_tscore_width_height(&width,&height);
 2474: 
 2475:   c_path_pp = (char **)capa_malloc( 4, sizeof(char *));
 2476:   tmp_len = strlen(class_fullpath) + 1;
 2477:   c_path_pp[0] = (char *)capa_malloc(tmp_len,sizeof(char));
 2478:   sprintf(c_path_pp[0],"%s",class_fullpath); /* c_path_pp[0] should always be there */
 2479:   
 2480:   entry_count = fs*2 + 1;
 2481:   S = (float *)capa_malloc( ((fs+1)*2), sizeof(float));
 2482:   F = (float *)capa_malloc( ((fs+1)*2), sizeof(float));
 2483:   X =   (int *)capa_malloc( ((fs+1)*2), sizeof(int));
 2484:   
 2485:   max_set[0] = set;  /* the login set number */
 2486:   hw_c = max_set[0];
 2487:   hw_r = homework_count - set;
 2488:   
 2489:   
 2490:   configResult=read_capa_config("quiz_path",buf);
 2491:   if (configResult != 0 && configResult != -1 ) {
 2492:     tmp_len = strlen(buf)+1;
 2493:     c_path_pp[1] = (char *)capa_malloc(tmp_len,sizeof(char));
 2494:     sprintf(c_path_pp[1],"%s",buf);
 2495:     max_set[1] = check_class_get_maxset(c_path_pp[1]);
 2496:     if( max_set[1] <= 0 ) {
 2497:       /* should we continue ? */
 2498:       max_set[1] = 1;
 2499:       X[1] = 1;
 2500:     }
 2501:     qz_c = max_set[1];
 2502:     qz_r = quiz_count - max_set[1];
 2503:   } else { /* if quiz_path is not in capa.config, then we will skip quizz */
 2504:     qz_c = 0;
 2505:     qz_r = 0;
 2506:   }
 2507:   
 2508:   
 2509:   configResult=read_capa_config("exam_path",buf);
 2510:   if (configResult != 0 && configResult != -1 ) {
 2511:     tmp_len = strlen(buf)+1;
 2512:     c_path_pp[2] = (char *)capa_malloc( (tmp_len),sizeof(char));
 2513:     sprintf(c_path_pp[2],"%s",buf);
 2514:     max_set[2] = check_class_get_maxset(c_path_pp[2]);
 2515:     printf("<!-- for %s max_set %d -->\n",c_path_pp[2],max_set[2]);
 2516:     if( max_set[2] <= 0 ) {
 2517: 	/* no sets */
 2518: 	max_set[2] = 0;
 2519:     }
 2520:     /* start extrapolation with sets that don't yet exist */
 2521:     for(idx=2+(max_set[2]*2);idx <= (fs*2); idx++) {
 2522:         X[idx] = 1;
 2523:     }
 2524:   } else { /* if exam_path is not in capa.config, then skip exams */
 2525:     fs = 0;
 2526:   }
 2527:   configResult=read_capa_config("correction_path",buf);
 2528:   if (configResult != 0 && configResult != -1 ) {
 2529:     tmp_len = strlen(buf)+1;
 2530:     c_path_pp[3] = (char *)capa_malloc(tmp_len,sizeof(char));
 2531:     sprintf(c_path_pp[3],"%s",buf);
 2532:     max_set[3] = check_class_get_maxset(c_path_pp[3]);
 2533:     if( max_set[3] <= 0 ) {
 2534:       /* should we continue ? */
 2535:       max_set[3] = 0;
 2536:       
 2537:     }
 2538:   } else { /* if correction_path is not in capa.config, then skip corrections */
 2539:     pc_w = 0.0;
 2540:   }
 2541:   
 2542:   
 2543:   
 2544:   for( idx = 0; idx < 4; idx++) {
 2545:      if( c_path_pp[idx] != NULL ) {
 2546:        chdir(c_path_pp[idx]);
 2547:        term_score=0;
 2548:        term_valid=0;
 2549:        for (set_idx=1; set_idx<=max_set[idx]; set_idx++) {
 2550:           if (capa_get_header(&header,set_idx))  return;
 2551:           capa_get_entry(&entry,student_number,set_idx);
 2552:           sscanf(header.num_questions,"%d", &(question_cnt) );
 2553:           valid_wgt = 0; set_score = 0;
 2554:           header.weight[question_cnt] = '\0';
 2555:           header.partial_credit[question_cnt] = '\0';
 2556:           for (i=0; i<question_cnt; i++) {
 2557:             valid_wgt +=  (header.weight[i] - '0');
 2558:             if((entry.answers[i]=='Y') || (entry.answers[i]=='y'))  
 2559: 	       set_score += (header.weight[i]-'0');
 2560:             if((entry.answers[i]=='E') || (entry.answers[i]=='e'))  
 2561: 	       valid_wgt -= (header.weight[i] - '0');
 2562:             if((entry.answers[i]>='0') && (entry.answers[i]<='9'))  
 2563: 	       set_score += (entry.answers[i] - '0');
 2564:           }
 2565:           term_valid += valid_wgt;
 2566:           term_score += set_score;
 2567:           capa_mfree(header.weight);
 2568:           capa_mfree(header.partial_credit);
 2569: 	  printf("<!-- %s %d %d -->\n",c_path_pp[idx],set_score,valid_wgt);
 2570:           if(idx==2) { /* exam sets */
 2571:             S[set_idx*2] = (float)set_score;
 2572:             F[set_idx*2] = (float)valid_wgt;
 2573:             if (valid_wgt == 0) {
 2574: 		X[set_idx*2] = 1;
 2575: 	    } else {
 2576: 		X[set_idx*2] = 0;
 2577: 	    }
 2578:           }
 2579:           if(idx==3) { /* correction sets */
 2580:             S[set_idx*2+1] = (float)set_score;
 2581:             F[set_idx*2+1] = (float)valid_wgt;
 2582: 	    if (valid_wgt == 0 ) {
 2583: 		X[set_idx*2+1] = 1;
 2584: 	    } else {
 2585: 		X[set_idx*2+1] = 0;
 2586: 	    }
 2587:           }
 2588:        }
 2589:        if( (idx == 0) || (idx==1) ) { /* homeworks and quizzes */
 2590:          S[idx] = (float)term_score;
 2591:          F[idx] = (float)term_valid;
 2592:          X[idx] = 1;
 2593:        }
 2594:      }
 2595:   }
 2596:   
 2597:   
 2598: 
 2599:   
 2600:   fprintf(out,"<CENTER>\n");
 2601:   fprintf(out,"<APPLET CODE=TScore.class CODEBASE=\"http://%s\" width=%d height=%d>\n",capa_server,width,height);
 2602:   fprintf(out,"<PARAM NAME=\"HW_W\"  VALUE=\"%f\">\n", hw_w);
 2603:   fprintf(out,"<PARAM NAME=\"QZ_W\"  VALUE=\"%f\">\n", qz_w);
 2604:   fprintf(out,"<PARAM NAME=\"EX_W\"  VALUE=\"%f\">\n", ex_w);
 2605:   fprintf(out,"<PARAM NAME=\"FE_W\"  VALUE=\"%f\">\n", fe_w);
 2606:   fprintf(out,"<PARAM NAME=\"PC_W\"  VALUE=\"%f\">\n", pc_w);
 2607:   fprintf(out,"<PARAM NAME=\"HW_C\"  VALUE=\"%d\">\n", hw_c);
 2608:   fprintf(out,"<PARAM NAME=\"HW_R\"  VALUE=\"%d\">\n", hw_r);
 2609:   fprintf(out,"<PARAM NAME=\"FS\"    VALUE=\"%d\">\n", fs);
 2610:   fprintf(out,"<PARAM NAME=\"QZ_C\"  VALUE=\"%d\">\n", qz_c);
 2611:   fprintf(out,"<PARAM NAME=\"QZ_R\"  VALUE=\"%d\">\n", qz_r);
 2612:   
 2613: 
 2614:   for(idx=0;idx<entry_count;idx++) {
 2615:     fprintf(out,"<PARAM NAME=\"S%d\"  VALUE=\"%f\">\n",idx,S[idx]);
 2616:     fprintf(out,"<PARAM NAME=\"F%d\"  VALUE=\"%f\">\n",idx,F[idx]);
 2617:     fprintf(out,"<PARAM NAME=\"X%d\"  VALUE=\"%d\">\n",idx,X[idx]);
 2618:   }
 2619:   
 2620:   fprintf(out,"</APPLET> </CENTER>\n");
 2621:   
 2622:   fprintf(out,"<TABLE cellpadding=0 cellspacing=0 border=0>\n<TR><TD>");
 2623:   fprintf(out,"<form method=\"post\" ");
 2624:   sprintf(buf,"action=\"http://%s/%s/%s/capasbin\">",serverName,g_cgibin_path,g_cowner);
 2625:   fprintf(out,"%s\n", buf);
 2626:   fprintf(out,"<input type=\"hidden\" name=\"CLASS\" value=\"%s\">\n",g_class_name);
 2627:   fprintf(out,"<input type=\"hidden\" name=\"SNUM\" value=\"%s\">\n",g_student_number);
 2628:   fprintf(out,"<input type=\"hidden\" name=\"CAPAID\" value=\"%d\">\n",g_entered_pin);
 2629:   fprintf(out,"<input type=\"hidden\" name=\"M\" value=\"%d\">\n",M_CHECKIN);
 2630:   fprintf(out,"<input type=\"submit\" value=\"Main menu\" ></form></TD>\n");
 2631:   fprintf(out,"<TD><form method=\"get\" action=\"http://%s/CAPA/class.html\">",serverName); 
 2632:   fprintf(out,"<input type=\"button\" value=\"Exit\" onclick=\"window.close()\"></form></TD>");
 2633:   fprintf(out,"\n</TABLE>\n");
 2634:   
 2635:   capa_mfree((char *)S);
 2636:   capa_mfree((char *)F);
 2637:   capa_mfree((char *)X);
 2638:   for(idx=0;idx<4;idx++) {
 2639:     if( c_path_pp[idx] != NULL )  capa_mfree((char *)c_path_pp[idx]);
 2640:   }
 2641:   capa_mfree((char *)c_path_pp);
 2642:   capa_mfree((char *)capa_server);
 2643: }
 2644: 
 2645: void
 2646: get_tscore_width_height(width,height) 
 2647: int *width;int *height;
 2648: {
 2649:   char     buf[MAX_BUFFER_SIZE]; 
 2650:   int      configResult;
 2651:   
 2652:   configResult=read_capa_config("tscore_width",buf);
 2653:   if (configResult != 0 && configResult != -1 ) {
 2654:     sscanf(buf,"%d", width);
 2655:     if (*width <= 0 )  { *width = DEFAULT_WIDTH; }
 2656:   } else {
 2657:       printf("<!-- tscore_width not found. %d-->\n",configResult);
 2658:   }
 2659:   configResult=read_capa_config("tscore_height",buf);
 2660:   if (configResult != 0 && configResult != -1 ) {
 2661:     sscanf(buf,"%d", height);
 2662:     if (*height <= 0 )  { *height = DEFAULT_HEIGHT; }
 2663:   } else {
 2664:       printf("<!-- tscore_height not found. %d-->\n",configResult);
 2665:   }
 2666: }
 2667: 
 2668: int
 2669: get_termscore_params(hw,qw,ew,fw,pw,hc,qc,fs) 
 2670: float *hw;float *qw;float *ew;float *fw;float *pw;
 2671: int   *hc;int   *qc;int   *fs;
 2672: {
 2673:   char     buf[MAX_BUFFER_SIZE]; /* Output line buffer  */
 2674:   int      hw_c, qz_c, fe_s;
 2675:   float    hw_w, qz_w, ex_w, fe_w, pc_w;
 2676:   int      configResult;
 2677:   
 2678:   configResult=read_capa_config("homework_weight",buf);
 2679:   if (configResult != 0 && configResult != -1 ) {
 2680:     sscanf(buf,"%f", &hw_w);
 2681:     if(hw_w <= 0.0 )  {
 2682:       hw_w = DEFAULT_HW_W;
 2683:     }
 2684:   } else {
 2685:     return (-1);
 2686:   }
 2687:   configResult=read_capa_config("quiz_weight",buf);
 2688:   if (configResult != 0 && configResult != -1 ) {
 2689:     sscanf(buf,"%f", &qz_w);
 2690:     if(qz_w <= 0.0 )  {
 2691:       qz_w = DEFAULT_QZ_W;
 2692:     }
 2693:   } else {
 2694:     return (-1);
 2695:   }
 2696:   configResult=read_capa_config("exam_weight",buf);
 2697:   if (configResult != 0 && configResult != -1 ) {
 2698:     sscanf(buf,"%f", &ex_w);
 2699:     if(ex_w <= 0.0 )  {
 2700:       ex_w = DEFAULT_EX_W;
 2701:     }
 2702:   } else {
 2703:     return (-1);
 2704:   }
 2705:   configResult=read_capa_config("final_weight",buf);
 2706:   if (configResult != 0 && configResult != -1 ) {
 2707:     sscanf(buf,"%f", &fe_w);
 2708:     if(fe_w <= 0.0 )  {
 2709:       fe_w = DEFAULT_FE_W;
 2710:     }
 2711:   } else {
 2712:     return (-1);
 2713:   }
 2714:   configResult=read_capa_config("correction_weight",buf);
 2715:   if (configResult != 0 && configResult != -1 ) {
 2716:     sscanf(buf,"%f", &pc_w);
 2717:     if(pc_w <= 0.0 )  {
 2718:       pc_w = DEFAULT_PC_W;
 2719:     }
 2720:   } else {
 2721:     return (-1);
 2722:   }
 2723:   configResult=read_capa_config("final_exam_set_number",buf);
 2724:   if (configResult != 0 && configResult != -1 ) {
 2725:     sscanf(buf,"%d", &fe_s);
 2726:     if(fe_s <= 0 )  {
 2727:       fe_s = DEFAULT_FE_NUMBER;
 2728:     }
 2729:   } else {
 2730:     return (-1);
 2731:   }
 2732:   configResult=read_capa_config("homework_count",buf);
 2733:   if (configResult != 0 && configResult != -1 ) {
 2734:     sscanf(buf,"%d", &hw_c);
 2735:     if(hw_c <= 0 )  {
 2736:       hw_c = DEFAULT_HW_COUNT;
 2737:     }
 2738:   } else {
 2739:     return (-1);
 2740:   }
 2741:   configResult=read_capa_config("quiz_count",buf);
 2742:   if (configResult != 0 && configResult != -1 ) {
 2743:     sscanf(buf,"%d", &qz_c);
 2744:     if(qz_c <= 0 )  {
 2745:       qz_c = DEFAULT_QZ_COUNT;
 2746:     }
 2747:   } else {
 2748:     return (-1);
 2749:   }
 2750:   *hw = hw_w; *qw = qz_w; *ew = ex_w; *fw = fe_w; *pw = pc_w;
 2751:   *hc = hw_c; *qc = qz_c; *fs = fe_s;
 2752:   return (0);
 2753: 
 2754: }
 2755: 
 2756: /* =================================================================================================== */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>