Annotation of loncom/homework/caparesponse/caparesponse.c, revision 1.25
1.7 albertel 1: /* The LearningOnline Network with CAPA
2: * CAPA wrapper code
1.25 ! raeburn 3: * $Id: caparesponse.c,v 1.24 2024/04/29 01:29:26 raeburn Exp $
1.7 albertel 4: *
5: * Copyright Michigan State University Board of Trustees
6: *
7: * This file is part of the LearningOnline Network with CAPA (LON-CAPA).
8: *
9: * LON-CAPA is free software; you can redistribute it and/or modify
10: * it under the terms of the GNU General Public License as published by
11: * the Free Software Foundation; either version 2 of the License, or
12: * (at your option) any later version.
13: *
14: * LON-CAPA is distributed in the hope that it will be useful,
15: * but WITHOUT ANY WARRANTY; without even the implied warranty of
16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: * GNU General Public License for more details.
18: *
19: * You should have received a copy of the GNU General Public License
20: * along with LON-CAPA; if not, write to the Free Software
21: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22: *
23: * /home/httpd/html/adm/gpl.txt
24: *
25: * http://www.lon-capa.org/
26: */
27:
1.1 albertel 28: #include <capaCommon.h>
1.6 albertel 29: #include <ranlib.h>
1.23 raeburn 30: #include <ctype.h> /* isdigit() */
1.6 albertel 31:
32: PointsList_t * parse_pts_list (char *pts_list) {
33: PointsList_t *new=NULL, *end=NULL, *beforeend=NULL, *rlist=NULL;
34: char *idx_pts=pts_list;
35: int done=0;
1.11 albertel 36: /*fprintf(stderr,"ids %s\n",id_list);
37: fprintf(stderr,"pts %s\n",pts_list);*/
1.18 albertel 38: while (!done && pts_list) {
1.6 albertel 39: int idx;
1.11 albertel 40: /*fprintf(stderr,"pts; %s\n",idx_pts);*/
1.6 albertel 41: new=gen_ptslist_str(idx_pts);
42: if (!new) break;
43: if (!rlist) { rlist=new; }
44: if (end) {
45: end->pts_next=new;
46: idx=end->pts_idx;
47: } else {
48: idx=-1;
49: }
50: end=new;
51: while (end) {
52: idx++;
53: end->pts_idx=idx;
1.11 albertel 54: /*fprintf(stderr,"end is:%d:%d:%s:%d\n",idx,end->pts_idx,end->pts_str,
55: end->pts_next);*/
1.6 albertel 56: beforeend=end;
57: end=end->pts_next;
58: }
59: end=beforeend;
60: idx_pts=strchr(idx_pts,';');
61: if (idx_pts) { idx_pts++; } else { done=1; }
62: }
63:
64: return rlist;
65: }
66:
1.1 albertel 67: int caparesponse_capa_check_answer(char *response,char *correct,
68: int type,int tol_type,double tolerance,
69: int sig_lbound,int sig_ubound,
70: char *ans_fmt, char *unit_str,
1.6 albertel 71: int calc, char *id_list, char *pts_list,
1.12 albertel 72: char *rndseed, char** reterror)
1.6 albertel 73:
1.1 albertel 74: {
1.6 albertel 75: long result,seed1,seed2;
1.1 albertel 76: Problem_t p;
77: char *error=NULL,filename[FILE_NAME_LENGTH];
78: FILE *fp;
1.11 albertel 79:
1.9 bowersj2 80: /* need to initialize unit parser*/
1.13 albertel 81: *reterror=NULL;
1.4 albertel 82: sprintf(filename,"/home/httpd/html/res/adm/includes/capa.units");
1.1 albertel 83: if ((fp=fopen(filename,"r"))==NULL) {
84: /* printf("Error: can't open %s\n",filename);*/
85: return (-1);
86: }
87: u_getunit(fp);
88: fclose(fp);
1.6 albertel 89: /* need to setup random generator (FIXME) should only do this if
90: it hasn't been yet*/
91: phrtsd(rndseed,&seed1,&seed2);
92: setall(seed1,seed2);
1.1 albertel 93:
1.6 albertel 94: /* assign_id_list and assign_pts_list exist in capaGrammerDef.y */
95: p.id_list=NULL;
96: p.pts_list=NULL;
1.11 albertel 97:
1.6 albertel 98: if (type == ANSWER_IS_FORMULA) {
99: p.id_list=id_list;
100: p.pts_list=parse_pts_list(pts_list);
1.19 albertel 101: // if ( p.id_list == NULL || p.pts_list == NULL) {
102: // return BAD_FORMULA;
103: // }
1.6 albertel 104: }
1.2 albertel 105: p.ans_type = type;
106: p.answer = correct;
107: p.tol_type = tol_type;
108: p.tolerance = tolerance;
109: p.sig_lbound = sig_lbound;
110: p.sig_ubound = sig_ubound;
1.8 bowersj2 111:
112: if (ans_fmt != NULL ) {
113: strncpy(p.ans_fmt,ans_fmt,ANSWER_STRING_LENG-1);
114: }
115: if (unit_str != NULL && unit_str[0]!='\0') {
1.5 albertel 116: strncpy(p.unit_str,unit_str,ANSWER_STRING_LENG-1);
1.17 albertel 117: //p.ans_unit = u_parse_unit(unit_str);
118: p.ans_unit = parse_unit_expr(unit_str);
119: p.ans_unit = process_utree(p.ans_unit);
120: //print_unit_t(p.ans_unit);
1.5 albertel 121: } else {
122: p.unit_str[0]='\0';
1.9 bowersj2 123: p.ans_unit=NULL;
1.5 albertel 124: }
1.2 albertel 125: p.calc = calc;
1.1 albertel 126:
127: result=capa_check_answer(&p,response,&error);
1.12 albertel 128: *reterror=error;
129: // Caller is expected to free reterror
130: // if (error!=NULL) {free(error);}
1.1 albertel 131:
132: return result;
133: }
1.14 albertel 134:
135: int caparesponse_get_real_response (char* unit_str, char* answer,
136: double* scaled) {
137: //double caparesponse_get_real_response (char* unit_str, char* answer) {
1.24 raeburn 138: int input_len,all_alphabet,idx,outcome=-1;
139: #pragma GCC diagnostic push
140: #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
141: int result;
142: #pragma GCC diagnostic pop
1.25 ! raeburn 143: double n_part,scale=1.0,given;
1.15 albertel 144: char input[ANSWER_STRING_LENG],filename[FILE_NAME_LENGTH],
145: tmp_unit_str[ANSWER_STRING_LENG];
1.14 albertel 146: Unit_t *ans_unit;
147: FILE *fp;
148: sprintf(filename,"/home/httpd/html/res/adm/includes/capa.units");
149: if ((fp=fopen(filename,"r"))==NULL) {
150: /* printf("Error: can't open %s\n",filename);*/
151: return (-1);
152: }
153: u_getunit(fp);
154: fclose(fp);
155:
156: if (unit_str != NULL && unit_str[0]!='\0') {
1.17 albertel 157: ans_unit = parse_unit_expr(unit_str);
158: ans_unit = process_utree(ans_unit);
1.14 albertel 159: } else {
160: ans_unit=NULL;
161: }
162: input_len = strlen(answer);
163: all_alphabet = 1;
164: for(idx=0;idx<input_len;idx++) {
165: if( isdigit(answer[idx]) ) {
166: all_alphabet = 0;
167: }
168: }
169: if( !all_alphabet ) {
1.19 albertel 170: tmp_unit_str[0] = 0;
1.15 albertel 171: outcome = split_num_unit(answer,&n_part,input,tmp_unit_str);
1.20 albertel 172: }
173: if( outcome > 0 ) {
1.14 albertel 174: if( outcome > 1 ) { /* with both num and unit parts or only unit part */
175: if( ans_unit != NULL ) {
1.15 albertel 176: result = check_correct_unit(tmp_unit_str,ans_unit,&scale);
1.14 albertel 177: } else {
178: /* what to do when no unit is specified but student entered a unit? */
179: result = UNIT_NOTNEEDED;
180: }
181: } else {
182: if( ans_unit != NULL ) {
183: result = NO_UNIT;
184: }
185: }
1.24 raeburn 186: #pragma GCC diagnostic push
187: #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1.14 albertel 188: if( (result != NO_UNIT) && (!check_for_unit_fail(result)) && ( result != UNIT_NOTNEEDED) ) {
189: given = n_part * scale;
190: *scaled=given;
191: /* convert the given answer into proper scale for units */
192: } /* end if unit check */
1.21 raeburn 193: } else { /* user entered alphabet, but no number */
1.14 albertel 194: result = WANTED_NUMERIC;
1.24 raeburn 195: }
196: #pragma GCC diagnostic pop
1.14 albertel 197: return result;
198: }
1.19 albertel 199:
1.21 raeburn 200: /* Testing harness
1.19 albertel 201: int main(void) {
202: int result=0;
203: char *reterror=NULL;
204: result= caparesponse_capa_check_answer("10^3","1000",
205: ANSWER_IS_FORMULA,
206: TOL_ABSOLUTE,1E-3,
207: 3,5,NULL,NULL,
208: CALC_UNFORMATED,
209: "","4",
210: "rndseed",
211: &reterror);
212: fprintf(stderr,"result %d\nreterror: %s\n",result,reterror);
213: }
214: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>