Diff for /capa/capa51/pProj/capaCommon.c between versions 1.12 and 1.24

version 1.12, 2000/06/30 21:36:16 version 1.24, 2004/06/01 19:57:18
Line 2 Line 2
    Copyright (C) 1992-2000 Michigan State University     Copyright (C) 1992-2000 Michigan State University
   
    The CAPA system is free software; you can redistribute it and/or     The CAPA system is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as     modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the     published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.     License, or (at your option) any later version.
   
    The CAPA system is distributed in the hope that it will be useful,     The CAPA system is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.     General Public License for more details.
   
    You should have received a copy of the GNU Library General Public     You should have received a copy of the GNU General Public
    License along with the CAPA system; see the file COPYING.  If not,     License along with the CAPA system; see the file COPYING.  If not,
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,     write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */     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 43  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 1442  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 2488  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 2627  answers_string(mode, p)int mode;Problem_ Line 2638  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 2649  answers_string(mode, p)int mode;Problem_ Line 2660  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 2886  answers_string(mode, p)int mode;Problem_ Line 2897  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 2910  capa_check_ans(ai,ans, error) AnswerInfo Line 2931  capa_check_ans(ai,ans, error) AnswerInfo
   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 2936  capa_check_ans(ai,ans, error) AnswerInfo Line 2957  capa_check_ans(ai,ans, error) AnswerInfo
               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 ) {
   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 2948  capa_check_ans(ai,ans, error) AnswerInfo Line 2970  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 3009  capa_check_ans(ai,ans, error) AnswerInfo Line 3031  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<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 3066  capa_check_answer(p, answer, error) Prob Line 3092  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[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 3081  capa_check_answer(p, answer, error) Prob Line 3108  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 3097  capa_check_answer(p, answer, error) Prob Line 3124  capa_check_answer(p, answer, error) Prob
               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 ) {
   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 3109  capa_check_answer(p, answer, error) Prob Line 3137  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 3170  capa_check_answer(p, answer, error) Prob Line 3198  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<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 3195  capa_check_answer(p, answer, error) Prob Line 3228  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 3202  capa_check_answer(p, answer, error) Prob Line 3239  capa_check_answer(p, answer, error) Prob
   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 3237  char *fml_str;char *input_str;char *var_ Line 3274  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 3362  Problem_t *p; char **answers; int cnt; c Line 3399  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 3378  Problem_t *p; char **answers; int cnt; c Line 3422  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 3389  Problem_t *p; char **answers; int cnt; c Line 3435  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 3413  Problem_t *p; char **answers; int cnt; c Line 3459  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 3431  Problem_t *p; char **answers; int cnt; c Line 3477  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 3532  char *key_word;char *value; Line 3578  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.12  
changed lines
  Added in v.1.24


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