/* The LearningOnline Network with CAPA
* CAPA wrapper code
* $Id: caparesponse.c,v 1.25 2024/04/29 03:06:39 raeburn 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>
#include <ctype.h> /* isdigit() */
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 && pts_list) {
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);
// if ( p.id_list == NULL || p.pts_list == NULL) {
// return BAD_FORMULA;
// }
}
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=-1;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
int result;
#pragma GCC diagnostic pop
double n_part,scale=1.0,given;
char input[ANSWER_STRING_LENG],filename[FILE_NAME_LENGTH],
tmp_unit_str[ANSWER_STRING_LENG];
Unit_t *ans_unit;
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] = 0;
outcome = split_num_unit(answer,&n_part,input,tmp_unit_str);
}
if( outcome > 0 ) {
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;
}
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
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 alphabet, but no number */
result = WANTED_NUMERIC;
}
#pragma GCC diagnostic pop
return result;
}
/* Testing harness
int main(void) {
int result=0;
char *reterror=NULL;
result= caparesponse_capa_check_answer("10^3","1000",
ANSWER_IS_FORMULA,
TOL_ABSOLUTE,1E-3,
3,5,NULL,NULL,
CALC_UNFORMATED,
"","4",
"rndseed",
&reterror);
fprintf(stderr,"result %d\nreterror: %s\n",result,reterror);
}
*/
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>