Diff for /capa/capa51/pProj/capaCommon.c between versions 1.2 and 1.22

version 1.2, 1999/10/13 18:45:28 version 1.22, 2002/09/20 21:27:49
Line 1 Line 1
   /* Library of useful functions
      Copyright (C) 1992-2000 Michigan State University
   
      The CAPA system is free software; you can redistribute it and/or
      modify it under the terms of the GNU General Public License as
      published by the Free Software Foundation; either version 2 of the
      License, or (at your option) any later version.
   
      The CAPA system is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      General Public License for more details.
   
      You should have received a copy of the GNU General Public
      License along with the CAPA system; see the file COPYING.  If not,
      write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
   
      As a special exception, you have permission to link this program
      with the TtH/TtM library and distribute executables, as long as you
      follow the requirements of the GNU GPL in regard to all of the
      software in the executable aside from TtH/TtM.
   */
   
 /* =||>|===================== capaCommon.c =====================|<||= */  /* =||>|===================== capaCommon.c =====================|<||= */
 /* created 1994 by Isaac Tsai                                         */  /* created 1994 by Isaac Tsai                                         */
 /* 1994, 1995, 1996, 1997, 1998, 1999  copyrighted by Isaac Tsai      */  
 /* TODO: restructure capa_check_ans*() calls into one                 */  /* TODO: restructure capa_check_ans*() calls into one                 */
 /* =||>|===================== capaCommon.c =====================|<||= */  /* =||>|===================== capaCommon.c =====================|<||= */
 #include <ctype.h>  #include <ctype.h>
Line 25  int     yyparse(); Line 48  int     yyparse();
 extern  FILE *yyin;  extern  FILE *yyin;
 extern  void yyrestart();  extern  void yyrestart();
   
   extern  FILE *dfp;
   
 /*----------------------------------------------------------*/  /*----------------------------------------------------------*/
 /*  RETURN: -1 file error                                   */  /*  RETURN: -1 file error                                   */
 /*           0 success                                      */  /*           0 success                                      */
Line 569  int        set; Line 594  int        set;
    }     }
    funlockstream(fp); fclose(fp);     funlockstream(fp); fclose(fp);
    if(!found) {     if(!found) {
      ans_p = capa_malloc(nq+1,1);        ans_p = capa_malloc(nq+2,1); 
      tries_p = capa_malloc(3*nq+2,1); /* space and \0 */       tries_p = capa_malloc(3*nq+3,1); /* space and \0 */
      for(ii=0;ii<nq;ii++) { /* Initialize answer string and tries string */       for(ii=0;ii<nq;ii++) { /* Initialize answer string and tries string */
        ans_p[ii] = '-'; tries_p[3*ii] = ' '; tries_p[3*ii + 1] = '0';         ans_p[ii] = '-'; tries_p[3*ii] = ' '; tries_p[3*ii + 1] = '0';
        if(ii < nq-1) tries_p[3*ii + 2] = ',';         if(ii < nq-1) tries_p[3*ii + 2] = ',';
Line 585  int        set; Line 610  int        set;
      comma=index(oneline,',');       comma=index(oneline,',');
      length=((int)(comma-oneline))-(MAX_STUDENT_NUMBER+1);       length=((int)(comma-oneline))-(MAX_STUDENT_NUMBER+1);
      if (length < nq) {       if (length < nq) {
        ans_p = capa_malloc(nq+1,1);          ans_p = capa_malloc(nq+2,1); 
        tries_p = capa_malloc(3*nq+2,1); /* space and \0 */         tries_p = capa_malloc(3*nq+3,1); /* space and \0 */
      } else {       } else {
        ans_p = capa_malloc(length+1,1);          ans_p = capa_malloc(length+2,1); 
        tries_p = capa_malloc(3*length+2,1); /* space and \0 */         tries_p = capa_malloc(3*length+3,1); /* space and \0 */
      }       }
      sprintf(fmtbuf, "%%%dc",length);       sprintf(fmtbuf, "%%%dc",length);
      sscanf(oneline + MAX_STUDENT_NUMBER+1,fmtbuf,ans_p);       sscanf(oneline + MAX_STUDENT_NUMBER+1,fmtbuf,ans_p);
        ans_p[length]='\0';
      sprintf(fmtbuf, "%%%dc",(3*length-1));       sprintf(fmtbuf, "%%%dc",(3*length-1));
      sscanf(oneline + MAX_STUDENT_NUMBER+1+length+1,fmtbuf,tries_p);       sscanf(oneline + MAX_STUDENT_NUMBER+1+length+1,fmtbuf,tries_p);
        tries_p[3*length-1]='\0';
      entry->answers = ans_p;       entry->answers = ans_p;
      entry->tries   = tries_p;       entry->tries   = tries_p;
      entry->e_probs = nq;       entry->e_probs = nq;
Line 1357  int capa_check_option(int option,int set Line 1384  int capa_check_option(int option,int set
 }  }
   
 /*----------------------------------------------------------*/  /*----------------------------------------------------------*/
 /* INPUT:  set             the X in logX.db                 */  /* INPUT:  time             the current time                */
   /*         datetime         the datetime string to compare  */
 /* OUTPUT: none                                             */  /* OUTPUT: none                                             */
 /*                                                          */  /*                                                          */
 /* RETURN:  -1    file error                                */  /* RETURN:  -1    time is earlier then datetime             */
 /*           0    no login                                  */  /*           1    time is later than datetime               */
 /*           >0   number of logins in that logX.db file     */  
 /*----------------------------------------------------------*/  /*----------------------------------------------------------*/
 int  int
 compare_datetime(time,datetime)  compare_datetime(time,datetime)
Line 1391  char   *datetime; Line 1418  char   *datetime;
 /* What if: [7,3] date_info  */  /* What if: [7,3] date_info  */
 /*          [3,7] date_info  */  /*          [3,7] date_info  */
 /*          4 date_info      */  /*          4 date_info      */
   /* RETURN:  -1    if not pass time                          */
   /*           1    if pass time (or no time available        */
 int capa_check_date(int which,char *student_number, int section,int set)  int capa_check_date(int which,char *student_number, int section,int set)
 {  {
   int result;    int result;
Line 1421  void capa_get_due_date(char *date_str,T_ Line 1449  void capa_get_due_date(char *date_str,T_
   if ((duration > 0) && (student_number!=NULL)) {    if ((duration > 0) && (student_number!=NULL)) {
     if (capa_get_login_time(student_number,set,&logintime)==1) {      if (capa_get_login_time(student_number,set,&logintime)==1) {
       duetime=logintime+duration;        duetime=logintime+duration;
       due_time_tm=localtime(&duetime);        if (compare_datetime(duetime,current->due_date)==-1) {
       sprintf(date_str,"%04d/%02d/%02d %02d:%02d",((due_time_tm->tm_year)+1900),   due_time_tm=localtime(&duetime);
       due_time_tm->tm_mon+1,due_time_tm->tm_mday,due_time_tm->tm_hour,   sprintf(date_str,"%04d/%02d/%02d %02d:%02d",((due_time_tm->tm_year)+1900),
       due_time_tm->tm_min);   due_time_tm->tm_mon+1,due_time_tm->tm_mday,due_time_tm->tm_hour,
    due_time_tm->tm_min);
         } else {
    strncpy(date_str,current->due_date,DATE_BUFFER); 
         }
       return;        return;
     }      }
   }     } 
Line 2121  extern  int        Symb_count; Line 2153  extern  int        Symb_count;
 extern  int        first_run;  extern  int        first_run;
 extern  int        Stop_Parser;  extern  int        Stop_Parser;
 extern  void       (*Status_Func)();  extern  void       (*Status_Func)();
   #ifdef TTH
   extern void tth_restart();
   extern char* tth_err;
   #endif /*TTH*/
   long  seed1,     seed2;    long  seed1,     seed2;
   T_student        a_student;    T_student        a_student;
   char            *class, *classname, warn_msg[WARN_MSG_LENGTH];    char            *class, *classname, warn_msg[WARN_MSG_LENGTH];
Line 2149  extern  void       (*Status_Func)(); Line 2185  extern  void       (*Status_Func)();
   }    }
   u_getunit(fp);    u_getunit(fp);
   fclose(fp);    fclose(fp);
   #ifdef TTH
     if(tth_err) { free(tth_err); tth_err=NULL; }
     tth_restart();
   #endif /*TTH*/
   strncpy(Parse_name,a_student.s_nm,MAX_NAME_CHAR+1);    strncpy(Parse_name,a_student.s_nm,MAX_NAME_CHAR+1);
   strncpy(Parse_student_number,student_number,MAX_STUDENT_NUMBER+1);    strncpy(Parse_student_number,student_number,MAX_STUDENT_NUMBER+1);
   Parse_section = a_student.s_sec;    Parse_section = a_student.s_sec;
Line 2459  char *buf;double *num; char *num_p; char Line 2499  char *buf;double *num; char *num_p; char
     while( isspace(buf[idx]) ) { idx++; }      while( isspace(buf[idx]) ) { idx++; }
     sscanf(num_str, "%lg", &result);  /* put the numerical value into a double variable */      sscanf(num_str, "%lg", &result);  /* put the numerical value into a double variable */
     errcode = errcode | 1;      errcode = errcode | 1;
   } else if( buf[idx] == 'x' || buf[idx] == 'X') { /* optional x or X part */    } else if( buf[idx] == 'x' || buf[idx] == 'X' || buf[idx] == '*') { /* optional x or X part */
     idx++; /* skip x or X */      idx++; /* skip x or X */
     while( isspace(buf[idx]) ) { idx++; }      while( isspace(buf[idx]) ) { idx++; }
           
Line 2609  answers_string(mode, p)int mode;Problem_ Line 2649  answers_string(mode, p)int mode;Problem_
                str_bb = format_toTeX(lower);                   str_bb = format_toTeX(lower);  
              } else { /* answer could be string, choice */               } else { /* answer could be string, choice */
                str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);                 str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
        if (p->ans_type == ANSWER_IS_FORMULA || 1)         if (p->verbatim == DO_VERBATIM)
  sprintf(str_bb,"\\begin{verbatim}%s\\end{verbatim}",lower);   sprintf(str_bb,"\\begin{verbatim}%s\\end{verbatim}",lower);
        else         else
  strcpy(str_bb,lower);   strcpy(str_bb,lower);
Line 2864  answers_string(mode, p)int mode;Problem_ Line 2904  answers_string(mode, p)int mode;Problem_
   
 /* <== This routine checks user input string *ans against correct answer *s ==> */  /* <== This routine checks user input string *ans against correct answer *s ==> */
 int  int
 capa_check_ans(ai,ans) AnswerInfo_t  *ai; char *ans;  capa_check_ans(ai,ans, error) AnswerInfo_t  *ai; char *ans; char **error;
 {  {
   int      t;     /* ans_type  */    int      t;     /* ans_type  */
   char    *s;     /* ans_str   */    char    *s;     /* ans_str   */
Line 2881  capa_check_ans(ai,ans) AnswerInfo_t  *ai Line 2921  capa_check_ans(ai,ans) AnswerInfo_t  *ai
   int      sig, corr_len;    int      sig, corr_len;
   int      choice[ANSWER_STRING_LENG];    int      choice[ANSWER_STRING_LENG];
   char     num_str[ANSWER_STRING_LENG], unit_str[ANSWER_STRING_LENG];    char     num_str[ANSWER_STRING_LENG], unit_str[ANSWER_STRING_LENG];
   char     fmted[ANSWER_STRING_LENG], correct[ANSWER_STRING_LENG], answer[ANSWER_STRING_LENG];    char     fmted[ANSWER_STRING_LENG], correctans[ANSWER_STRING_LENG], answer[ANSWER_STRING_LENG];
   double   n_part;    double   n_part;
   double   given, target, ratio, fmted_target, target_u, target_l, scale=1.0;    double   given, target, ratio, fmted_target, target_u, target_l, scale=1.0;
   double   delta;    double   delta;
Line 2907  capa_check_ans(ai,ans) AnswerInfo_t  *ai Line 2947  capa_check_ans(ai,ans) AnswerInfo_t  *ai
               outcome = split_num_unit(ans,&n_part,num_str,unit_str);                outcome = split_num_unit(ans,&n_part,num_str,unit_str);
               if( outcome > 1 ) { /* with both num and unit parts or only unit part */                if( outcome > 1 ) { /* with both num and unit parts or only unit part */
                 if( u_p != NULL ) {                  if( u_p != NULL ) {
                   result = check_correct_unit(unit_str,u_p,&scale);    if (UNIT_FAIL == (result = check_correct_unit(unit_str,u_p,&scale))) {
       *error=strsave(unit_str);
     }
                 } else { /* what to do when no unit is specified but student entered a unit? */                  } else { /* what to do when no unit is specified but student entered a unit? */
                   result = UNIT_NOTNEEDED;                    result = UNIT_NOTNEEDED;
     *error=strsave(unit_str);
                 }                  }
               } else {                } else {
                 if( u_p != NULL ) {                  if( u_p != NULL ) {
Line 2924  capa_check_ans(ai,ans) AnswerInfo_t  *ai Line 2967  capa_check_ans(ai,ans) AnswerInfo_t  *ai
                 }                  }
                 given = n_part * scale; /* convert the given answer into proper scale for units */                  given = n_part * scale; /* convert the given answer into proper scale for units */
                 sig = calc_sig( num_str );                  sig = calc_sig( num_str );
                 if( (sig < sl) || (sig > su) ) {                  if( ((sig < sl   ) || (sig > su   )) && (sig!=0)) {
                   result = SIG_FAIL;    result = SIG_FAIL;
     *error=capa_malloc(1,ANSWER_STRING_LENG);
     sprintf(*error,"%d",sig);
                 } else {                  } else {
                   switch( tt ) { /* tolerence type */                    switch( tt ) { /* tolerence type */
                    case TOL_ABSOLUTE:                     case TOL_ABSOLUTE:
Line 2967  capa_check_ans(ai,ans) AnswerInfo_t  *ai Line 3012  capa_check_ans(ai,ans) AnswerInfo_t  *ai
                 } /* end sig check */                  } /* end sig check */
               } /* end if unit check */                } /* end if unit check */
             } else { /* user entered alphabets, but no number */              } else { /* user entered alphabets, but no number */
               result = INCORRECT;                result = WANTED_NUMERIC;
             }               } 
           }            }
           break;            break;
Line 2975  capa_check_ans(ai,ans) AnswerInfo_t  *ai Line 3020  capa_check_ans(ai,ans) AnswerInfo_t  *ai
           {            {
             corr_len = strlen(s); input_len = strlen(ans);              corr_len = strlen(s); input_len = strlen(ans);
             if( corr_len == input_len ) {              if( corr_len == input_len ) {
               for(idx=0;idx<ANSWER_STRING_LENG;idx++) choice[idx] = 0;                for(idx=0;idx<ANSWER_STRING_LENG;idx++) {
    choice[idx] = 0;correctans[idx] = 0;
         }
               result = EXACT_ANS;                result = EXACT_ANS;
               for(ii=0;ii<corr_len; ii++) {                for(ii=0;ii<corr_len; ii++) {
                 idx = toupper(correct[ii]) - 'A'; choice[idx] =  1;                  idx = toupper(s[ii]) - 'A'; choice[idx] =  1;
               }                }
               for(ii=0;ii<input_len;ii++) {                for(ii=0;ii<input_len;ii++) {
                 idx = toupper(answer[ii]) - 'A';                  idx = toupper(ans[ii]) - 'A'; correctans[idx] = 1;
                 if(choice[idx] != 1 )  result = INCORRECT;        }
         for(ii=0;ii<ANSWER_STRING_LENG;ii++) {
    if(choice[ii] != correctans[ii] )  result = INCORRECT;
               }                }
             } else { result = INCORRECT; }              } else { result = INCORRECT; }
             break;              break;
Line 2997  capa_check_ans(ai,ans) AnswerInfo_t  *ai Line 3046  capa_check_ans(ai,ans) AnswerInfo_t  *ai
           result = check_formula_ans(s,ans,ai->ans_id_list,ai->ans_pts_list,tt,to);            result = check_formula_ans(s,ans,ai->ans_id_list,ai->ans_pts_list,tt,to);
           break;            break;
     case ANSWER_IS_EXTERNAL: /* Not yet implemented */      case ANSWER_IS_EXTERNAL: /* Not yet implemented */
             
             
             
           break;            break;
   }    }
   return (result);    return (result);
Line 3019  capa_check_ans(ai,ans) AnswerInfo_t  *ai Line 3071  capa_check_ans(ai,ans) AnswerInfo_t  *ai
   
   
 int  int
 capa_check_answer(p, answer) Problem_t *p; char *answer;  capa_check_answer(p, answer, error) Problem_t *p; char *answer; char **error;
 {  {
   int     type;     int     type; 
   char   *correct;    char   *correct;
Line 3029  capa_check_answer(p, answer) Problem_t * Line 3081  capa_check_answer(p, answer) Problem_t *
   int     sig_l;     int     sig_l; 
   int     sig_u;    int     sig_u;
   char   *fmt;    char   *fmt;
   int     choice[ANSWER_STRING_LENG], ii, idx, corr_len, input_len;    int     choice[ANSWER_STRING_LENG], correctans[ANSWER_STRING_LENG];
     int     ii, idx, corr_len, input_len;
   int     result = INCORRECT, sig, outcome, all_alphabet;    int     result = INCORRECT, sig, outcome, all_alphabet;
   char    fmted[FORMAT_STRING_LENG];    char    fmted[FORMAT_STRING_LENG];
   double  given, target, ratio, fmted_target, target_u, target_l, scale=1.0;    double  given, target, ratio, fmted_target, target_u, target_l, scale=1.0;
Line 3060  capa_check_answer(p, answer) Problem_t * Line 3113  capa_check_answer(p, answer) Problem_t *
               outcome = split_num_unit(answer,&n_part,input,unit_str);                outcome = split_num_unit(answer,&n_part,input,unit_str);
               if( outcome > 1 ) { /* with both num and unit parts or only unit part */                if( outcome > 1 ) { /* with both num and unit parts or only unit part */
                 if( p->ans_unit != NULL ) {                  if( p->ans_unit != NULL ) {
                   result = check_correct_unit(unit_str,p->ans_unit,&scale);    if ( UNIT_FAIL == ( result = check_correct_unit(unit_str,p->ans_unit,&scale) ) ) {
                       *error=strsave(unit_str);
     }
                 } else { /* what to do when no unit is specified but student entered a unit? */                  } else { /* what to do when no unit is specified but student entered a unit? */
                   result = UNIT_NOTNEEDED;                    result = UNIT_NOTNEEDED;
     *error=strsave(unit_str);
                 }                  }
               } else {                } else {
                 if( p->ans_unit != NULL ) {                  if( p->ans_unit != NULL ) {
Line 3078  capa_check_answer(p, answer) Problem_t * Line 3133  capa_check_answer(p, answer) Problem_t *
                 }                  }
                 given = n_part * scale; /* convert the given answer into proper scale for units */                  given = n_part * scale; /* convert the given answer into proper scale for units */
                 sig = calc_sig( input );                  sig = calc_sig( input );
                 if( (sig < sig_l) || (sig > sig_u) ) {                  if( ((sig < sig_l) || (sig > sig_u)) && (sig!=0)) {
                   result = SIG_FAIL;                    result = SIG_FAIL;
     *error=capa_malloc(1,ANSWER_STRING_LENG);
     sprintf(*error,"%d",sig);
                 } else {                  } else {
                   switch( tol_type ) {                    switch( tol_type ) {
                    case TOL_ABSOLUTE:                     case TOL_ABSOLUTE:
Line 3121  capa_check_answer(p, answer) Problem_t * Line 3178  capa_check_answer(p, answer) Problem_t *
                 } /* end sig check */                  } /* end sig check */
               } /* end if unit check */                } /* end if unit check */
             } else { /* user entered alphabet, but no number */              } else { /* user entered alphabet, but no number */
               result = INCORRECT;                result = WANTED_NUMERIC;
             }               } 
           }            }
           break;            break;
Line 3129  capa_check_answer(p, answer) Problem_t * Line 3186  capa_check_answer(p, answer) Problem_t *
           {            {
             corr_len = strlen(correct); input_len = strlen(answer);              corr_len = strlen(correct); input_len = strlen(answer);
             if( corr_len == input_len ) {              if( corr_len == input_len ) {
               for(ii=0;ii<ANSWER_STRING_LENG;ii++) choice[ii] = 0;  result = EXACT_ANS;                for(idx=0;idx<ANSWER_STRING_LENG;idx++) {
    choice[idx] = 0;correctans[idx] = 0;
         }
                 result = EXACT_ANS;
               for(ii=0;ii<corr_len; ii++) {                for(ii=0;ii<corr_len; ii++) {
                 idx = toupper(correct[ii]) - 'A'; choice[idx] =  1;                  idx = toupper(correct[ii]) - 'A'; choice[idx] =  1;
               }                }
               for(ii=0;ii<input_len;ii++) {                for(ii=0;ii<input_len;ii++) {
                 idx = toupper(answer[ii]) - 'A';                  idx = toupper(answer[ii]) - 'A'; correctans[idx] = 1;
                 if(choice[idx] != 1 )  result = INCORRECT;        }
         for(ii=0;ii<ANSWER_STRING_LENG;ii++) {
    if(choice[ii] != correctans[ii] )  result = INCORRECT;
               }                }
             } else { result = INCORRECT; }              } else { result = INCORRECT; }
             break;              break;
Line 3150  capa_check_answer(p, answer) Problem_t * Line 3212  capa_check_answer(p, answer) Problem_t *
           result = check_formula_ans(correct,answer,p->id_list,p->pts_list,tol_type,tol);            result = check_formula_ans(correct,answer,p->id_list,p->pts_list,tol_type,tol);
           break;            break;
     case ANSWER_IS_EXTERNAL: /* not yet implemented */      case ANSWER_IS_EXTERNAL: /* not yet implemented */
            /* we assume the external program is called through popen() */
            /* and the result will be given back as 0 or 1 to indicate the */
            /* given answer is correct or not */
            /* arguments are given to the program as */
            /* before running the program, check its existance first */
            /* should we specify a time out period in capa.config file? */
            /* set up a timer for this purpose */
            /* FILE *popen (const char *command,const char *type ); */
   
           break;            break;
           
   }    }
   return (result);    return (result);
 }  }
   
 /* ----------------------------------------------------------------------------------- */  /* -------------------------------------------------------------------------- */
 /*   assumming the formula is *fml_str and the student input is *input_str             */  /*   assumming the formula is *fml_str and the student input is *input_str             */
 /*   according to the type of tolerance, we form the final formula as                  */  /*   according to the type of tolerance, we form the final formula as                  */
 /*      absolute tolerance:  (*fml_str) - (*input_str)                                 */  /*      absolute tolerance:  (*fml_str) - (*input_str)                                 */
Line 3191  char *fml_str;char *input_str;char *var_ Line 3262  char *fml_str;char *input_str;char *var_
         }          }
       } else {        } else {
         diff = abs(1.0 - formula_val) * 100.0 ;          diff = abs(1.0 - formula_val) * 100.0 ;
         if( diff < tol ) {          if( diff > tol ) {
           outcome = INCORRECT;            outcome = INCORRECT;
         }          }
       }        }
Line 3301  int tol_type;double tol;char *lower;char Line 3372  int tol_type;double tol;char *lower;char
 /* New check answers routine checks the /AND and /OR group of answers */  /* New check answers routine checks the /AND and /OR group of answers */
 /*   use array of char pointers  char **a */  /*   use array of char pointers  char **a */
 int  int
 capa_check_answers(p,answers,cnt) Problem_t *p; char **answers; int cnt;  capa_check_answers(p,answers,cnt,error) 
   Problem_t *p; char **answers; int cnt; char **error;
 {  {
   AnswerInfo_t  *ai;    AnswerInfo_t  *ai;
   int            ii, done, result;    int            ii, done, result;
   int           *outcomes;    int           *outcomes;
     char          **errormsg;
       
     errormsg=(char**)capa_malloc(cnt,sizeof(char*));
   if(p->ans_op == ANS_AND) {  /* ans /and ans */    if(p->ans_op == ANS_AND) {  /* ans /and ans */
     if( (cnt != p->ans_cnt) ) { return (ANS_CNT_NOT_MATCH); }      if( (cnt != p->ans_cnt) ) { return (ANS_CNT_NOT_MATCH); }
     if( cnt == 1 ) { return (capa_check_answer(p, answers[0])); } /* there is only one answer */      if( cnt == 1 ) { return (capa_check_answer(p, answers[0], error)); } /* there is only one answer */
     outcomes = (int *)capa_malloc(sizeof(int),cnt);      outcomes = (int *)capa_malloc(sizeof(int),cnt);
     for(ii=0;ii<cnt;ii++) outcomes[ii]=0;  /* initialize the outcomes array */      for(ii=0;ii<cnt;ii++) outcomes[ii]=0;  /* initialize the outcomes array */
     outcomes[0] = capa_check_answer(p, answers[0]);      outcomes[0] = capa_check_answer(p, answers[0], &errormsg[0]);
   #ifdef    COMMON_DBUG
       printf("CAPA_CHECK_ANSWER(%s,%s):: outcome[0]=%d\n", 
          p->answer,answers[0],outcomes[0]); 
   #endif
     for(ii=1, ai = p->ans_list; ai; ii++,ai = ai->ans_next  ) {      for(ii=1, ai = p->ans_list; ai; ii++,ai = ai->ans_next  ) {
        outcomes[ii] =  capa_check_ans(ai,answers[ii]);         outcomes[ii] =  capa_check_ans(ai,answers[ii],&(errormsg[ii]));
   #ifdef    COMMON_DBUG
       printf("CAPA_CHECK_ANS(%s,%s): outcome[%d]=%d\n", ai->ans_str,answers[ii],ii,outcomes[ii]); 
   #endif
     }      }
     done = ii = 0;      done = ii = 0;
     result = 0;      result = 0;
Line 3323  capa_check_answers(p,answers,cnt) Proble Line 3404  capa_check_answers(p,answers,cnt) Proble
           (outcomes[ii] == NO_UNIT)   ||            (outcomes[ii] == NO_UNIT)   ||
           (outcomes[ii] == UNIT_NOTNEEDED) ) {            (outcomes[ii] == UNIT_NOTNEEDED) ) {
          result = outcomes[ii];           result = outcomes[ii];
    if (result != NO_UNIT) { *error=strsave(errormsg[ii]); }
          done = 1;           done = 1;
       }        }
       ii++;        ii++;
       if(ii==cnt) done = 1;        if(ii==cnt) done = 1;
     }      }
     if( result == 0 ) { /* check if any of the outcome has failed on sig figs */      if( result == 0 ) { 
       /* check if any of the outcome has failed to be a numeric 
          or was a malformed equation */
         done = ii = 0;
         while( !done ) {
           if( outcomes[ii] == WANTED_NUMERIC || outcomes[ii] == BAD_FORMULA ) {
             result = outcomes[ii];
             done = 1;
           }
           ii++;
           if(ii==cnt) done = 1;
         }
       }
       if( result == 0 ) {/*check if any of the outcome has failed on sig figs*/
       done = ii = 0;        done = ii = 0;
       while( !done ) {        while( !done ) {
         if( outcomes[ii] == SIG_FAIL ) {          if( outcomes[ii] == SIG_FAIL ) {
           result = outcomes[ii];            result = outcomes[ii];
     *error = strsave(errormsg[ii]);
           done = 1;            done = 1;
         }          }
         ii++;          ii++;
Line 3350  capa_check_answers(p,answers,cnt) Proble Line 3446  capa_check_answers(p,answers,cnt) Proble
         if(ii==cnt) done = 1;          if(ii==cnt) done = 1;
       }        }
     }      }
       for (ii=0;ii<cnt;ii++) {
         if( (outcomes[ii] == UNIT_FAIL) ||
             (outcomes[ii] == SIG_FAIL)   ||
             (outcomes[ii] == UNIT_NOTNEEDED) ) {
    capa_mfree(errormsg[ii]);
         }
       }
       capa_mfree((char *)errormsg);
     capa_mfree((char *)outcomes);      capa_mfree((char *)outcomes);
     if( result == 0 ) {      if( result == 0 ) {
       result = APPROX_ANS; /* all answers are correct */        result = APPROX_ANS; /* all answers are correct */
     }      }
         
   } else { /* should be ANS_OR , user answer count should always be 1 */    } else { /* should be ANS_OR , user answer count should always be 1 */
      if( cnt != 1 ) { return (ANS_CNT_NOT_MATCH); }       if( cnt != 1 ) { return (ANS_CNT_NOT_MATCH); }
      if( p->ans_cnt == 1 ) { return (capa_check_answer(p, answers[0])); }       if( p->ans_cnt == 1 ) { return (capa_check_answer(p, answers[0], error)); }
      result = capa_check_answer(p, answers[0]);       result = capa_check_answer(p, answers[0], error);
      ii = 1;  ai = p->ans_list;       ii = 1;  ai = p->ans_list;
      while( (ii<p->ans_cnt) && ( (result != EXACT_ANS) && (result != APPROX_ANS) ) ) {       while( (ii<p->ans_cnt) && ( (result != EXACT_ANS) && (result != APPROX_ANS) ) ) {
          result =  capa_check_ans(ai,answers[0]);         if((ii!=1)&&((result==UNIT_FAIL)||(result==SIG_FAIL)||(result==UNIT_NOTNEEDED))) {
          ai = ai->ans_next; ii++;   capa_mfree((char*)error);
          }
          result =  capa_check_ans(ai,answers[0],error);
          ai = ai->ans_next; ii++;
      }       }
   }    }
   return (result);    return (result);
Line 3458  char *key_word;char *value; Line 3566  char *key_word;char *value;
   }    }
  }   }
  if (c=='\n') found=1;   if (c=='\n') found=1;
  if (((char)c)==((char)EOF)) break;   if (((char)c)==((char)EOF)) {failed=1;break;}
       }        }
     }      }
   } while (!done && !failed);     } while (!done && !failed); 
Line 3466  char *key_word;char *value; Line 3574  char *key_word;char *value;
   fclose(fp);    fclose(fp);
   
   if (done) {    if (done) {
       trim_response_ws(right); /*get rid of leading and trailing spaces*/
     for(i=0,j=0;i<(strlen(right)+1);i++) {      for(i=0,j=0;i<(strlen(right)+1);i++) {
       value[j]='\0';        value[j]='\0';
       if (right[i] == '\\' && (i < (strlen(right))) ) {        if (right[i] == '\\' && (i < (strlen(right))) ) {

Removed from v.1.2  
changed lines
  Added in v.1.22


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