File:  [LON-CAPA] / capa / capa51 / pProj / capaCgiUtils.c
Revision 1.21: download - view: text, annotated - select for diffs
Tue Oct 10 20:03:23 2000 UTC (23 years, 8 months ago) by albertel
Branches: MAIN
CVS tags: version_2_9_99_0, version_2_8_X, version_2_8_99_1, version_2_8_99_0, version_2_8_2, version_2_8_1, version_2_8_0, version_2_7_X, version_2_7_99_1, version_2_7_99_0, version_2_7_1, version_2_7_0, version_2_6_X, version_2_6_99_1, version_2_6_99_0, version_2_6_3, version_2_6_2, version_2_6_1, version_2_6_0, version_2_5_X, version_2_5_99_1, version_2_5_99_0, version_2_5_2, version_2_5_1, version_2_5_0, version_2_4_X, version_2_4_99_0, version_2_4_2, version_2_4_1, version_2_4_0, version_2_3_X, version_2_3_99_0, version_2_3_2, version_2_3_1, version_2_3_0, version_2_2_X, version_2_2_99_1, version_2_2_99_0, version_2_2_2, version_2_2_1, version_2_2_0, version_2_1_X, version_2_1_99_3, version_2_1_99_2, version_2_1_99_1, version_2_1_99_0, version_2_1_3, version_2_1_2, version_2_1_1, version_2_1_0, version_2_0_X, version_2_0_99_1, version_2_0_2, version_2_0_1, version_2_0_0, version_1_99_3, version_1_99_2, version_1_99_1_tmcc, version_1_99_1, version_1_99_0_tmcc, version_1_99_0, version_1_3_X, version_1_3_3, version_1_3_2, version_1_3_1, version_1_3_0, version_1_2_X, version_1_2_99_1, version_1_2_99_0, version_1_2_1, version_1_2_0, version_1_1_X, version_1_1_99_5, version_1_1_99_4, version_1_1_99_3, version_1_1_99_2, version_1_1_99_1, version_1_1_99_0, version_1_1_3, version_1_1_2, version_1_1_1, version_1_1_0, version_1_0_99_3, version_1_0_99_2, version_1_0_99_1, version_1_0_99, version_1_0_3, version_1_0_2, version_1_0_1, version_1_0_0, version_0_99_5, version_0_99_4, version_0_99_3, version_0_99_2, version_0_99_1, version_0_99_0, version_0_6_2, version_0_6, version_0_5_1, version_0_5, version_0_4, stable_2002_spring, stable_2002_july, stable_2002_april, stable_2001_fall, conference_2003, bz6209-base, bz6209, STABLE, HEAD, GCI_3, GCI_2, GCI_1, CAPA_5-1-6, CAPA_5-1-5, CAPA_5-1-4_RC1
- was stripping needed tabs from submission strings

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

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