Diff for /capa/capa51/pProj/capaCommon.c between versions 1.10 and 1.30

version 1.10, 2000/03/22 21:08:03 version 1.30, 2024/04/27 16:36:30
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 125  funlockstream(sp) FILE *sp; Line 150  funlockstream(sp) FILE *sp;
   
 int  int
 inquery_a_lock(sp,cmd,type,offset,whence,len)  inquery_a_lock(sp,cmd,type,offset,whence,len)
 FILE *sp;int cmd;off_t offset;int whence;off_t len;  FILE *sp;int cmd;short int type;off_t offset;int whence;off_t len;
 {  {
   struct flock lock;    struct flock lock;
   int    fd;    int    fd;
Line 1424  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 2124  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 2152  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 2417  check_input_usymb(u_symb)char *u_symb; Line 2454  check_input_usymb(u_symb)char *u_symb;
 /*          num_p  : the numerical part in string */  /*          num_p  : the numerical part in string */
 /*          unit_p : the unit string */  /*          unit_p : the unit string */
 /* num_p is used to calculate sig figs */  /* num_p is used to calculate sig figs */
 /* return :   0  empty string          */  /* return :  -1  invalid string        */
   /*            0  empty string          */
 /*            1  number without units  */  /*            1  number without units  */
 /*            2  empty number with units */  /*            2  empty number with units */
 /*            3  number with units       */  /*            3  number with units       */
Line 2462  char *buf;double *num; char *num_p; char Line 2500  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++; }
           
     e_part = 1.0;  /* default power */      e_part = 1.0;  /* default power */
     base_str[b_idx] = 0; /* initialize base_str[] */      base_str[b_idx] = 0; /* initialize base_str[] */
     while( isdigit(buf[idx]) || buf[idx] == '.' ) { /* should start with a digit or . */      if( buf[idx] == '1' && buf[idx+1] == '0') {
       base_str[b_idx++] = buf[idx++];        base_str[b_idx++] = buf[idx++];
         base_str[b_idx++] = buf[idx++];
       } else {
         return (-1);
     }      }
     base_str[b_idx] = 0; /* terminate base_str[] */      base_str[b_idx] = 0; /* terminate base_str[] */
     while( isspace(buf[idx]) ) { idx++; } /* skip over white spaces */      while( isspace(buf[idx]) ) { idx++; } /* skip over white spaces */
Line 2483  char *buf;double *num; char *num_p; char Line 2524  char *buf;double *num; char *num_p; char
       while( isspace(buf[idx]) ) { idx++; }        while( isspace(buf[idx]) ) { idx++; }
       if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' )  {        if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' )  {
         exp_str[e_idx] = 0;  /* initialize exp_str[], again */          exp_str[e_idx] = 0;  /* initialize exp_str[], again */
         while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {          while( isdigit(buf[idx]) /*|| buf[idx] == '.'*/ || buf[idx] == '+' || buf[idx] == '-' ) {
           exp_str[e_idx++] = buf[idx++];            exp_str[e_idx++] = buf[idx++];
         }          }
         exp_str[e_idx] = 0;  /* terminate exp_str[] */          exp_str[e_idx] = 0;  /* terminate exp_str[] */
Line 2517  char *buf;double *num; char *num_p; char Line 2558  char *buf;double *num; char *num_p; char
     while( isspace(buf[idx]) ) { idx++; }      while( isspace(buf[idx]) ) { idx++; }
     if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' )  {      if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' )  {
         exp_str[e_idx] = 0;          exp_str[e_idx] = 0;
         while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {          while( isdigit(buf[idx]) /*|| buf[idx] == '.'*/ || buf[idx] == '+' || buf[idx] == '-' ) {
           exp_str[e_idx++] = buf[idx++];            exp_str[e_idx++] = buf[idx++];
         }          }
         exp_str[e_idx] = 0;          exp_str[e_idx] = 0;
Line 2528  char *buf;double *num; char *num_p; char Line 2569  char *buf;double *num; char *num_p; char
     }      }
     sscanf(exp_str, "%lg", &e_part);      sscanf(exp_str, "%lg", &e_part);
     sscanf(num_str, "%lg", &n_part);      sscanf(num_str, "%lg", &n_part);
       if( n_part != 10 ) {
         return (-1);
       }
     result = pow(n_part,e_part);      result = pow(n_part,e_part);
     errcode = errcode | 1;      errcode = errcode | 1;
   } else {  /* number unit */    } else {  /* number unit */
Line 2601  answers_string(mode, p)int mode;Problem_ Line 2645  answers_string(mode, p)int mode;Problem_
              if(len_dd == 0 ) {  /* no unit_str */               if(len_dd == 0 ) {  /* no unit_str */
                sprintf(ans_str," %s [%s,%s]\n\n", str_aa,str_bb,str_cc);                 sprintf(ans_str," %s [%s,%s]\n\n", str_aa,str_bb,str_cc);
              } else {               } else {
                sprintf(ans_str," %s [%s,%s] $%s$\n\n", str_aa,str_bb,str_cc,p->unit_str);                 sprintf(ans_str," %s [%s,%s] $\\mathrm{%s}$\n\n", str_aa,str_bb,str_cc,p->unit_str);
              }               }
              capa_mfree((char *)str_aa);                capa_mfree((char *)str_aa); 
      capa_mfree((char *)str_bb);        capa_mfree((char *)str_bb); 
Line 2623  answers_string(mode, p)int mode;Problem_ Line 2667  answers_string(mode, p)int mode;Problem_
              if(len_dd == 0 ) {  /* no unit_str */               if(len_dd == 0 ) {  /* no unit_str */
                sprintf(ans_str," %s\n", str_bb);                 sprintf(ans_str," %s\n", str_bb);
              } else {               } else {
                sprintf(ans_str," %s $%s$\n", str_bb,p->unit_str);                 sprintf(ans_str," %s $\\mathrm{%s}$\n", str_bb,p->unit_str);
              }               }
              capa_mfree((char *)str_bb);               capa_mfree((char *)str_bb);
            }             }
Line 2860  answers_string(mode, p)int mode;Problem_ Line 2904  answers_string(mode, p)int mode;Problem_
 }  }
   
   
   int check_for_unit_fail(int result)
   {
     int ret;
     ret = (result == UNIT_FAIL ||
    result == UNIT_IRRECONCIBLE ||
    result == UNIT_INVALID_STUDENT3 ||
    result == UNIT_INVALID_STUDENT2 ||
    result == UNIT_INVALID_STUDENT1);
     return ret;
   }
   
 /* ------------------------------ called from capalogin */  /* ------------------------------ called from capalogin */
 /*  impose stronger checking on the user input string *answer   */  /*  impose stronger checking on the user input string *answer   */
Line 2880  capa_check_ans(ai,ans, error) AnswerInfo Line 2934  capa_check_ans(ai,ans, error) AnswerInfo
   char    *us;    /* ans_unit_str */    char    *us;    /* ans_unit_str */
   Unit_t  *u_p;   /* ans_unit     */    Unit_t  *u_p;   /* ans_unit     */
   int      input_len, all_alphabet = 1, idx, ii, type;    int      input_len, all_alphabet = 1, idx, ii, type;
   int      outcome, result = INCORRECT;    int      outcome=-1, result = INCORRECT;
   int      sig, corr_len;    int      sig, corr_len;
   int      choice[ANSWER_STRING_LENG];    int      choice[MAX_ASCII];
   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[MAX_ASCII], 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 2906  capa_check_ans(ai,ans, error) AnswerInfo Line 2960  capa_check_ans(ai,ans, error) AnswerInfo
                 all_alphabet = 0;                  all_alphabet = 0;
               }                }
             }              }
             if( !all_alphabet ) { /* answer string is not all alphabets */              if( !all_alphabet ) {
               outcome = split_num_unit(ans,&n_part,num_str,unit_str);                outcome = split_num_unit(ans,&n_part,num_str,unit_str);
       }
       if( outcome > 0 ) {
               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 ) {
   if (UNIT_FAIL == (result = check_correct_unit(unit_str,u_p,&scale))) {    result = check_correct_unit(unit_str,u_p,&scale);
     if (check_for_unit_fail(result)) {
     *error=strsave(unit_str);      *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? */
Line 2922  capa_check_ans(ai,ans, error) AnswerInfo Line 2979  capa_check_ans(ai,ans, error) AnswerInfo
                   result = NO_UNIT;                    result = NO_UNIT;
                 }                  }
               }                }
               if( (result != NO_UNIT) && (result != UNIT_FAIL) && ( result != UNIT_NOTNEEDED) ) {                if( (result != NO_UNIT) && (!check_for_unit_fail(result)) && ( result != UNIT_NOTNEEDED) ) {
                 if( t == ANSWER_IS_FLOAT ) {                  if( t == ANSWER_IS_FLOAT ) {
                   target = (double)atof(s); /* real number */                    target = (double)atof(s); /* real number */
                 } else {                  } else {
Line 2983  capa_check_ans(ai,ans, error) AnswerInfo Line 3040  capa_check_ans(ai,ans, error) AnswerInfo
           {            {
             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<MAX_ASCII;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]); 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]); correctans[idx] = 1;
                 if(choice[idx] != 1 )  result = INCORRECT;        }
         for(ii=0;ii<MAX_ASCII;ii++) {
    if(choice[ii] != correctans[ii] )  result = INCORRECT;
               }                }
             } else { result = INCORRECT; }              } else { result = INCORRECT; }
             break;              break;
Line 3040  capa_check_answer(p, answer, error) Prob Line 3101  capa_check_answer(p, answer, error) Prob
   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[MAX_ASCII], correctans[MAX_ASCII];
   int     result = INCORRECT, sig, outcome, all_alphabet;    int     ii, idx, corr_len, input_len;
     int     result = INCORRECT, sig, outcome=-1, 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;
   double  delta;    double  delta;
Line 3055  capa_check_answer(p, answer, error) Prob Line 3117  capa_check_answer(p, answer, error) Prob
   fmt      = p->ans_fmt;    fmt      = p->ans_fmt;
   calc_type = p->calc;    calc_type = p->calc;
   unit_str[0]=0;    unit_str[0]=0;
     
   switch(type) {    switch(type) {
     case ANSWER_IS_INTEGER:      case ANSWER_IS_INTEGER:
     case ANSWER_IS_FLOAT:      case ANSWER_IS_FLOAT:
Line 3069  capa_check_answer(p, answer, error) Prob Line 3131  capa_check_answer(p, answer, error) Prob
             }              }
             if( !all_alphabet ) {              if( !all_alphabet ) {
               outcome = split_num_unit(answer,&n_part,input,unit_str);                outcome = split_num_unit(answer,&n_part,input,unit_str);
       }
       if( outcome > 0 ) {
               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 ) {
   if ( UNIT_FAIL == ( result = check_correct_unit(unit_str,p->ans_unit,&scale) ) ) {    result = check_correct_unit(unit_str,p->ans_unit,&scale);
     if (check_for_unit_fail(result)) {
     *error=strsave(unit_str);      *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? */
Line 3083  capa_check_answer(p, answer, error) Prob Line 3148  capa_check_answer(p, answer, error) Prob
                   result = NO_UNIT;                    result = NO_UNIT;
                 }                  }
               }                }
               if( (result != NO_UNIT) && (result != UNIT_FAIL) && ( result != UNIT_NOTNEEDED) ) {                if( (result != NO_UNIT) && (!check_for_unit_fail(result)) && ( result != UNIT_NOTNEEDED) ) {
                 if( type == ANSWER_IS_FLOAT ) {                  if( type == ANSWER_IS_FLOAT ) {
                   target = (double)atof(correct); /* real number */                    target = (double)atof(correct); /* real number */
                 } else {                  } else {
Line 3144  capa_check_answer(p, answer, error) Prob Line 3209  capa_check_answer(p, answer, error) Prob
           {            {
             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<MAX_ASCII;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]); 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]); correctans[idx] = 1;
                 if(choice[idx] != 1 )  result = INCORRECT;        }
         for(ii=0;ii<MAX_ASCII;ii++) {
    if(choice[ii] != correctans[ii] ) result = INCORRECT;
               }                }
             } else { result = INCORRECT; }              } else { result = INCORRECT; }
             break;              break;
Line 3169  capa_check_answer(p, answer, error) Prob Line 3239  capa_check_answer(p, answer, error) Prob
          /* and the result will be given back as 0 or 1 to indicate the */           /* and the result will be given back as 0 or 1 to indicate the */
          /* given answer is correct or not */           /* given answer is correct or not */
          /* arguments are given to the program as */           /* 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;
           
Line 3176  capa_check_answer(p, answer, error) Prob Line 3250  capa_check_answer(p, answer, error) Prob
   return (result);    return (result);
 }  }
   
 /* ----------------------------------------------------------------------------------- */  int check_tol (formula_val,tol_type,tol)
   double formula_val;int tol_type;double tol;
   {
     double diff;
     int outcome=APPROX_ANS;
     if( tol_type == TOL_ABSOLUTE ) {
       diff = tol - formula_val;
       if( diff < 0.0 )  {
         outcome = INCORRECT;
       }
     } else {
       diff = fabs(1.0 - formula_val) * 100.0 ;
       if( diff > tol ) {
         outcome = INCORRECT;
       }
     }
     return outcome;
   }
   
   /* -------------------------------------------------------------------------- */
 /*   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 3188  char *fml_str;char *input_str;char *var_ Line 3281  char *fml_str;char *input_str;char *var_
   char         *check_fml_str;    char         *check_fml_str;
   int           f_len, i_len, outcome, error_code;    int           f_len, i_len, outcome, error_code;
   PointsList_t *pt, *next;    PointsList_t *pt, *next;
   double        formula_val, diff;    double        formula_val;
       
   f_len = strlen(fml_str);    f_len = strlen(fml_str);
   i_len = strlen(input_str);    i_len = strlen(input_str);
Line 3200  char *fml_str;char *input_str;char *var_ Line 3293  char *fml_str;char *input_str;char *var_
     sprintf(check_fml_str,"(%s) / (%s)",input_str,fml_str);      sprintf(check_fml_str,"(%s) / (%s)",input_str,fml_str);
   }    }
   outcome = APPROX_ANS;    outcome = APPROX_ANS;
     if( pts_list==NULL ) {
       error_code = f_eval_formula(&formula_val,check_fml_str, var_list, NULL);
       if( ! error_code ) {
         outcome = check_tol(formula_val,tol_type,tol);
       } else {
         outcome = BAD_FORMULA;
       }      
     }
   
   for(pt= pts_list; pt!=NULL ; pt=next) {    for(pt= pts_list; pt!=NULL ; pt=next) {
     next=pt->pts_next;      next=pt->pts_next;
     error_code = f_eval_formula(&formula_val,check_fml_str, var_list, pt->pts_str);      error_code = f_eval_formula(&formula_val,check_fml_str, var_list, pt->pts_str);
     if( ! error_code ) {      if( ! error_code ) {
       if( tol_type == TOL_ABSOLUTE ) {        outcome = check_tol(formula_val,tol_type,tol);
         diff = tol - formula_val;  
         if( diff < 0.0 )  {  
           outcome = INCORRECT;  
         }  
       } else {  
         diff = abs(1.0 - formula_val) * 100.0 ;  
         if( diff < tol ) {  
           outcome = INCORRECT;  
         }  
       }  
     } else {      } else {
       outcome = BAD_FORMULA;        outcome = BAD_FORMULA;
       break;        break;
     }      }
       if (outcome != APPROX_ANS) {
         break;
       }
   }    }
   capa_mfree((char *)check_fml_str);    capa_mfree((char *)check_fml_str);
       
Line 3336  Problem_t *p; char **answers; int cnt; c Line 3431  Problem_t *p; char **answers; int cnt; c
     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], &errormsg[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],&(errormsg[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;
     while( !done ) { /* check if any of the outcome has failed on units */      while( !done ) { /* check if any of the outcome has failed on units */
       if( (outcomes[ii] == UNIT_FAIL) ||        if( (check_for_unit_fail(outcomes[ii])) ||
           (outcomes[ii] == NO_UNIT)   ||            (outcomes[ii] == NO_UNIT)   ||
           (outcomes[ii] == UNIT_NOTNEEDED) ) {            (outcomes[ii] == UNIT_NOTNEEDED) ) {
          result = outcomes[ii];           result = outcomes[ii];
Line 3352  Problem_t *p; char **answers; int cnt; c Line 3454  Problem_t *p; char **answers; int cnt; c
       ii++;        ii++;
       if(ii==cnt) done = 1;        if(ii==cnt) done = 1;
     }      }
     if( result == 0 ) { /* check if any of the outcome has failed to be a numeric */      if( result == 0 ) { 
       /* check if any of the outcome has failed to be a numeric 
          or was a malformed equation */
       done = ii = 0;        done = ii = 0;
       while( !done ) {        while( !done ) {
         if( outcomes[ii] == WANTED_NUMERIC ) {          if( outcomes[ii] == WANTED_NUMERIC || outcomes[ii] == BAD_FORMULA ) {
           result = outcomes[ii];            result = outcomes[ii];
           done = 1;            done = 1;
         }          }
Line 3363  Problem_t *p; char **answers; int cnt; c Line 3467  Problem_t *p; char **answers; int cnt; c
         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 on sig figs*/
       done = ii = 0;        done = ii = 0;
       while( !done ) {        while( !done ) {
         if( outcomes[ii] == SIG_FAIL ) {          if( outcomes[ii] == SIG_FAIL ) {
Line 3387  Problem_t *p; char **answers; int cnt; c Line 3491  Problem_t *p; char **answers; int cnt; c
       }        }
     }      }
     for (ii=0;ii<cnt;ii++) {      for (ii=0;ii<cnt;ii++) {
       if( (outcomes[ii] == UNIT_FAIL) ||        if( (check_for_unit_fail(outcomes[ii])) ||
           (outcomes[ii] == SIG_FAIL)   ||            (outcomes[ii] == SIG_FAIL)   ||
           (outcomes[ii] == UNIT_NOTNEEDED) ) {            (outcomes[ii] == UNIT_NOTNEEDED) ) {
  capa_mfree(errormsg[ii]);   capa_mfree(errormsg[ii]);
Line 3405  Problem_t *p; char **answers; int cnt; c Line 3509  Problem_t *p; char **answers; int cnt; c
      result = capa_check_answer(p, answers[0], error);       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) ) ) {
        if((ii!=1)&&((result==UNIT_FAIL)||(result==SIG_FAIL)||(result==UNIT_NOTNEEDED))) {         if((ii!=1)&&((check_for_unit_fail(result))||(result==SIG_FAIL)||(result==UNIT_NOTNEEDED))) {
  capa_mfree((char*)error);   capa_mfree((char*)error);
        }         }
        result =  capa_check_ans(ai,answers[0],error);         result =  capa_check_ans(ai,answers[0],error);
Line 3506  char *key_word;char *value; Line 3610  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); 

Removed from v.1.10  
changed lines
  Added in v.1.30


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