File:  [LON-CAPA] / loncom / homework / caparesponse / caparesponse.c
Revision 1.17: download - view: text, annotated - select for diffs
Tue Feb 15 22:15:05 2005 UTC (19 years, 2 months ago) by albertel
Branches: MAIN
CVS tags: version_2_0_X, 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, HEAD
- BUG#3952, the instructor's unit was being parsed by the stupid, but fast unit parser, swapping it out so that the instructor's parser is the same as the one used to parse the students's answer

/* The LearningOnline Network with CAPA 
 * CAPA wrapper code
 * $Id: caparesponse.c,v 1.17 2005/02/15 22:15:05 albertel Exp $
 *
 * Copyright Michigan State University Board of Trustees
 *
 * This file is part of the LearningOnline Network with CAPA (LON-CAPA).
 *
 * LON-CAPA 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.
 *
 * LON-CAPA 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 LON-CAPA; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * /home/httpd/html/adm/gpl.txt
 *
 * http://www.lon-capa.org/
 */

#include <capaCommon.h>
#include <ranlib.h>

PointsList_t * parse_pts_list (char *pts_list) {
  PointsList_t *new=NULL, *end=NULL, *beforeend=NULL, *rlist=NULL;
  char *idx_pts=pts_list;
  int done=0;
  /*fprintf(stderr,"ids %s\n",id_list);
    fprintf(stderr,"pts %s\n",pts_list);*/
  while (!done) {
    int idx;
    /*fprintf(stderr,"pts; %s\n",idx_pts);*/
    new=gen_ptslist_str(idx_pts);
    if (!new) break;
    if (!rlist) { rlist=new; }
    if (end) { 
      end->pts_next=new; 
      idx=end->pts_idx;
    } else {
      idx=-1;
    }
    end=new;
    while (end) {
      idx++;
      end->pts_idx=idx;
      /*fprintf(stderr,"end is:%d:%d:%s:%d\n",idx,end->pts_idx,end->pts_str,
	end->pts_next);*/
      beforeend=end;
      end=end->pts_next;
    }
    end=beforeend;
    idx_pts=strchr(idx_pts,';');
    if (idx_pts) { idx_pts++; } else { done=1; }
  }
  
  return rlist;
}

int caparesponse_capa_check_answer(char *response,char *correct,
				   int type,int tol_type,double tolerance,
				   int sig_lbound,int sig_ubound, 
				   char *ans_fmt, char *unit_str,
				   int calc, char *id_list, char *pts_list, 
				   char *rndseed, char** reterror)
				   
{
  long result,seed1,seed2;
  Problem_t p;
  char *error=NULL,filename[FILE_NAME_LENGTH];
  FILE *fp;

  /* need to initialize unit parser*/
  *reterror=NULL;
  sprintf(filename,"/home/httpd/html/res/adm/includes/capa.units");
  if ((fp=fopen(filename,"r"))==NULL) {
    /* printf("Error: can't open %s\n",filename);*/
      return (-1); 
  }
  u_getunit(fp);
  fclose(fp);
  /* need to setup random generator (FIXME) should only do this if 
     it hasn't been yet*/
  phrtsd(rndseed,&seed1,&seed2);
  setall(seed1,seed2);

  /* assign_id_list and assign_pts_list exist in capaGrammerDef.y */
  p.id_list=NULL;
  p.pts_list=NULL;

  if (type == ANSWER_IS_FORMULA) {
    p.id_list=id_list;
    p.pts_list=parse_pts_list(pts_list);
  }
  p.ans_type   = type;
  p.answer     = correct;
  p.tol_type   = tol_type;
  p.tolerance  = tolerance;
  p.sig_lbound = sig_lbound;
  p.sig_ubound = sig_ubound;
  
  if (ans_fmt != NULL ) {
    strncpy(p.ans_fmt,ans_fmt,ANSWER_STRING_LENG-1);
  }
  if (unit_str != NULL && unit_str[0]!='\0') {
    strncpy(p.unit_str,unit_str,ANSWER_STRING_LENG-1);
    //p.ans_unit = u_parse_unit(unit_str);
    p.ans_unit   = parse_unit_expr(unit_str);
    p.ans_unit   = process_utree(p.ans_unit);
    //print_unit_t(p.ans_unit);
  } else {
    p.unit_str[0]='\0';
    p.ans_unit=NULL;
  }
  p.calc       = calc;

  result=capa_check_answer(&p,response,&error);
  *reterror=error;
  // Caller is expected to free reterror
  //  if (error!=NULL) {free(error);}

  return result;
}

int caparesponse_get_real_response (char* unit_str, char* answer,
				    double* scaled) {
  //double caparesponse_get_real_response (char* unit_str, char* answer) {
  int     input_len,all_alphabet,idx,outcome,result;
  double  n_part,scale=1.0,given,target;
  char    input[ANSWER_STRING_LENG],filename[FILE_NAME_LENGTH],
    tmp_unit_str[ANSWER_STRING_LENG];
  Unit_t *ans_unit;
  long    seed1,seed2;
  FILE   *fp;
  sprintf(filename,"/home/httpd/html/res/adm/includes/capa.units");
  if ((fp=fopen(filename,"r"))==NULL) {
    /* printf("Error: can't open %s\n",filename);*/
    return (-1); 
  }
  u_getunit(fp);
  fclose(fp);

  if (unit_str != NULL && unit_str[0]!='\0') {
    ans_unit   = parse_unit_expr(unit_str);
    ans_unit   = process_utree(ans_unit);
  } else {
    ans_unit=NULL;
  }
  input_len = strlen(answer);
  all_alphabet = 1;
  for(idx=0;idx<input_len;idx++) {
    if( isdigit(answer[idx]) ) {
      all_alphabet = 0;
    }
  }
  if( !all_alphabet ) {
    tmp_unit_str[0]=NULL;
    outcome = split_num_unit(answer,&n_part,input,tmp_unit_str);
    if( outcome > 1 ) { /* with both num and unit parts or only unit part */
      if( ans_unit != NULL ) {
	result = check_correct_unit(tmp_unit_str,ans_unit,&scale);
      } else {
	/* what to do when no unit is specified but student entered a unit? */
	result = UNIT_NOTNEEDED;
      }
    } else {
      if( ans_unit != NULL ) {
	result = NO_UNIT;
      }
    }
    if( (result != NO_UNIT) && (!check_for_unit_fail(result)) && ( result != UNIT_NOTNEEDED) ) {
      given = n_part * scale;
      *scaled=given;
      /* convert the given answer into proper scale for units */
    } /* end if unit check */
  } else { /* user entered a
lphabet, but no number */
    result = WANTED_NUMERIC;
  } 
  return result;
}

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