Rev 17465 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
10 | reyssat | 1 | /* Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis |
2 | * |
||
3 | * This program is free software; you can redistribute it and/or modify |
||
4 | * it under the terms of the GNU General Public License as published by |
||
5 | * the Free Software Foundation; either version 2 of the License, or |
||
6 | * (at your option) any later version. |
||
7 | * |
||
8 | * This program is distributed in the hope that it will be useful, |
||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
11 | * GNU General Public License for more details. |
||
12 | * |
||
13 | * You should have received a copy of the GNU General Public License |
||
14 | * along with this program; if not, write to the Free Software |
||
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||
16 | */ |
||
17 | |||
18 | #include <utime.h> |
||
8185 | bpr | 19 | #include "wims.h" |
10 | reyssat | 20 | |
7673 | bpr | 21 | /* Subroutines to process examinations */ |
10 | reyssat | 22 | |
23 | char eparm[MAX_LINELEN+1]; |
||
24 | |||
25 | void exam_parm(void) |
||
26 | { |
||
12245 | bpr | 27 | char *p1, *p2, *p3; |
28 | int v; |
||
29 | setvar("module_init_parm",eparm); |
||
30 | for(v=0,p1=eparm; *p1; p1=p2) { |
||
31 | while(*p1=='&') p1++; |
||
32 | p2=strchr(p1,'&'); |
||
33 | if(p2==NULL) p2=p1+strlen(p1); else *p2++=0; |
||
34 | p3=strchr(p1,'='); if(p3==NULL) continue; else *p3++=0; |
||
35 | p1=find_word_start(p1); *find_word_end(p1)=0; |
||
36 | p3=find_word_start(p3); strip_trailing_spaces(p3); |
||
37 | user_variable[v].name=p1; user_variable[v].value=p3; |
||
38 | v++; |
||
39 | } |
||
40 | user_var_no=v; |
||
10 | reyssat | 41 | } |
42 | |||
7673 | bpr | 43 | /* prepare examination situation */ |
10 | reyssat | 44 | void check_exam(void) |
45 | { |
||
12245 | bpr | 46 | char *p, *p2, *e1, *e2, *pc=NULL; |
47 | char ps[64], pb[64], cbuf[64], dbuf[64], vbuf[MAX_FNAME+1]; |
||
48 | int t1, t2; |
||
49 | int start, duration, remain; |
||
50 | double prime; |
||
51 | struct stat st; |
||
10 | reyssat | 52 | |
12245 | bpr | 53 | p=getvar(ro_name[ro_session]); |
54 | if(p==NULL || (p2=strstr(p,"_exam"))==NULL) return; |
||
55 | mystrncpy(pb,p,sizeof(pb)); p=pb; |
||
56 | p2=strstr(p,"_exam"); if(p2==NULL) return; else *p2=0; |
||
10 | reyssat | 57 | |
12245 | bpr | 58 | if(strchr(p2+1,'t')==NULL) { |
59 | e1=getvar(ro_name[ro_worksheet]); |
||
60 | if(e1==NULL || *e1==0) { |
||
61 | bad: user_error("bad_exam"); return; |
||
10 | reyssat | 62 | } |
12245 | bpr | 63 | e2=strchr(e1,'.'); if(e2==NULL) goto bad; |
64 | e2++; t1=atoi(e1); t2=atoi(e2); |
||
65 | } |
||
66 | else { |
||
67 | char *pt1,*pt2; |
||
68 | pt1=strchr(p2+1,'t'); pt2=strchr(pt1+1,'t'); |
||
69 | *pt1++=0; *pt2++=0; t1=atoi(pt1); t2=atoi(pt2); |
||
70 | } |
||
71 | if(t1<1 || t1>99 || t2<1 || t2>99) goto bad; |
||
72 | snprintf(ps,sizeof(ps),"%s_examt%dt%d",p,t1,t2); |
||
73 | isexam=1; setsesdir(ps); force_setvar("wims_isexam","1"); |
||
74 | force_setvar(ro_name[ro_session],ps); |
||
13168 | bpr | 75 | /* get exam setup data */ |
12245 | bpr | 76 | accessfile(cbuf,"r","%s/%s/examdata.%d", session_dir,pb,t1); |
77 | if(cbuf[0]==0) goto bad; |
||
78 | p=find_word_start(cbuf); p2=find_word_end(p); if(*p2) *p2++=0; |
||
79 | duration=atoi(p)*60; if(duration==0) goto bad; |
||
80 | if(*p2) prime=atof(p2); else prime=0; |
||
81 | if (strstr(ps,parent_dir_string)!=NULL) user_error("wrong_session"); |
||
13168 | bpr | 82 | /* Whether the exercise is already done */ |
12245 | bpr | 83 | p=getvar(ro_name[ro_cmd]); if(p!=NULL) { |
84 | if(strcmp(p,"getins")==0 || strcmp(p,"getframe")==0) goto skipped; |
||
85 | } |
||
86 | exam_currscore(t1); |
||
87 | if(exam_scoredata[t2-1]!=-1000) { |
||
88 | snprintf(dbuf,sizeof(dbuf),"%.1f",exam_scoredata[t2-1]); |
||
89 | setvar("wims_exo_lastscore",dbuf); |
||
13168 | bpr | 90 | /* Do we need to erase subsession? */ |
17616 | bpr | 91 | /* cannot see the page of the statement because of the user_error */ |
12245 | bpr | 92 | user_error("exam_exo_finished"); |
93 | } |
||
94 | skipped: |
||
95 | snprintf(session_prefix,sizeof(session_prefix),"%s/%s",session_dir,ps); |
||
96 | snprintf(vbuf,sizeof(vbuf),"%s/var",session_prefix); |
||
97 | if(stat(vbuf,&st)==0) { /* exists */ |
||
98 | unsetvar("module"); |
||
99 | p=getvar(ro_name[ro_cmd]); |
||
100 | if(p==NULL) { |
||
101 | recmd: |
||
102 | force_setvar(ro_name[ro_cmd],commands[cmd_resume]); |
||
103 | user_var_no=0; |
||
10 | reyssat | 104 | } |
12245 | bpr | 105 | else { |
106 | int i; |
||
107 | for(i=0;i<CMD_NO && strcmp(p,commands[i]);i++); |
||
108 | if(i>=CMD_NO || i==cmd_intro || i==cmd_new || i==cmd_renew || i==cmd_hint) |
||
109 | goto recmd; |
||
10 | reyssat | 110 | } |
12245 | bpr | 111 | } |
112 | else { /* new */ |
||
113 | char *pt, cbuf[MAX_FNAME+1], ebuf[MAX_FNAME+1]; |
||
114 | char buf[2][MAX_LINELEN+1]; |
||
115 | int w1,w2; |
||
7673 | bpr | 116 | |
12245 | bpr | 117 | force_setvar(ro_name[ro_cmd],commands[cmd_new]); |
118 | get_static_session_var(); |
||
7673 | bpr | 119 | |
12245 | bpr | 120 | pc=getvar("wims_class"); if(pc==NULL) pc=""; |
121 | snprintf(cbuf,sizeof(cbuf),"%s/%s",class_base,pc); |
||
122 | snprintf(ebuf,sizeof(ebuf),"%s/exams/.exam%d",cbuf,t1); |
||
123 | direct_datafile=1; |
||
124 | datafile_fnd_record(ebuf,t2,buf[0]); |
||
125 | direct_datafile=0; |
||
126 | if(buf[0][0]==0) goto bad; |
||
127 | fnd_line(buf[0],4,buf[1]); |
||
128 | if(buf[1][0]!=0) { /* dependencies */ |
||
129 | if(!exam_depcheck(buf[1],t1)) { |
||
130 | user_error("exam_dep"); |
||
131 | } |
||
10 | reyssat | 132 | } |
12245 | bpr | 133 | fnd_line(buf[0],2,buf[1]); if(buf[1][0]==0) goto bad; |
134 | calc_randitem(buf[1]); |
||
135 | pt=strchr(buf[1],'.'); |
||
136 | if(pt==NULL) { |
||
137 | bad2: module_error("bad_exam_2"); return; |
||
138 | } |
||
139 | snprintf(exam_sheetexo,sizeof(exam_sheetexo)," %s",buf[1]); |
||
140 | *pt++=0; w1=atoi(buf[1]); w2=atoi(pt); |
||
141 | if(w1<1 || w1>99 || w2<1 || w2>99) goto bad2; |
||
142 | snprintf(ebuf,sizeof(ebuf),"%s/sheets/.sheet%d",cbuf,w1); |
||
143 | direct_datafile=1; |
||
144 | datafile_fnd_record(ebuf,w2,buf[0]); |
||
145 | direct_datafile=0; |
||
146 | if(buf[0][0]==0) goto bad2; |
||
147 | fnd_line(buf[0],1,buf[1]); if(buf[1][0]==0) goto bad2; |
||
148 | force_setvar(ro_name[ro_module],buf[1]); |
||
149 | fnd_line(buf[0],2,eparm); /* if(eparm[0]==0) goto bad2; */ |
||
150 | exam_parm(); |
||
151 | } |
||
17451 | guerimand | 152 | get_static_session_var(); |
17255 | guerimand | 153 | /* detect open exam in other session and forbidden open a new */ |
154 | char *pu, pbuf1[MAX_LINELEN+1]; |
||
17435 | guerimand | 155 | if(pc==NULL) pc=getvar("wims_class"); |
156 | if(pc==NULL) pc=""; |
||
17255 | guerimand | 157 | pu=getvar("wims_user"); if(pu==NULL) pu=""; |
17435 | guerimand | 158 | /* line not needed at this step make directory is done later |
17255 | guerimand | 159 | snprintf(pbuf1,sizeof(pbuf1),"%s/%s/.parmreg", class_base, pc); |
17435 | guerimand | 160 | mkdirs(pbuf1);*/ |
17255 | guerimand | 161 | snprintf(pbuf1,sizeof(pbuf1),"%s/%s/.parmreg/%s.exam",class_base, pc, pu); |
162 | if(stat(pbuf1,&st)==0) { /* search for other session ?? */ |
||
163 | /* read file pbuf1 */ |
||
164 | char pbuf2[MAX_LINELEN+1], *pf1, *pf2; |
||
165 | accessfile(pbuf2,"r",pbuf1); |
||
166 | pf1=find_word_start(find_word_end(find_word_start(pbuf2)));pf2=find_word_end(pf1); |
||
167 | memmove(pbuf2,pf1,pf2-pf1);pbuf2[pf2-pf1]=0; |
||
17415 | guerimand | 168 | if( strcmp(pbuf2,pb)!=0 && strcmp("supervisor",pu)!=0 ) { /* other exam session open */ |
17255 | guerimand | 169 | user_error("other_exam_session"); return; |
170 | } |
||
171 | } |
||
172 | /* end of add for detect */ |
||
173 | |||
13168 | bpr | 174 | /* Register start time */ |
12245 | bpr | 175 | snprintf(vbuf,sizeof(vbuf),"%s/%s/examreg.%d", |
176 | session_dir,pb,t1); |
||
177 | if(stat(vbuf,&st)==0) { /* reg exists */ |
||
178 | char tbuf[MAX_LINELEN+1]; |
||
179 | struct utimbuf ut; |
||
180 | accessfile(tbuf,"r",vbuf); start=atoi(tbuf); |
||
181 | if(start<=nowtime-duration) { |
||
182 | user_error("expired_exam"); return; |
||
13168 | bpr | 183 | } |
184 | /* refresh session times */ |
||
185 | ut.actime=ut.modtime=nowtime; |
||
186 | utime(mkfname(NULL,"%s/%s",session_dir,pb),&ut); |
||
12245 | bpr | 187 | } |
188 | else { /* First time call: register starting time */ |
||
17255 | guerimand | 189 | char *p1, tbuf[MAX_LINELEN+1]; |
12245 | bpr | 190 | snprintf(dbuf,sizeof(dbuf),"%u",(unsigned int) nowtime); |
191 | accessfile(dbuf,"w","%s",vbuf); start=nowtime; |
||
17616 | bpr | 192 | /* variable initializing before |
12245 | bpr | 193 | if(pc==NULL) pc=getvar("wims_class"); |
194 | if(pc==NULL) pc=""; |
||
17435 | guerimand | 195 | pu=getvar("wims_user"); if(pu==NULL) pu="";*/ |
196 | snprintf(vbuf,sizeof(vbuf),"%s/%s/.parmreg", class_base, pc); |
||
197 | mkdirs(vbuf); |
||
12245 | bpr | 198 | snprintf(vbuf,sizeof(vbuf),"%s/%s/.parmreg/%s.exam", |
199 | class_base, pc, pu); |
||
200 | p1=remote_addr; |
||
201 | snprintf(dbuf,sizeof(dbuf),"%s %s %u %d", |
||
202 | p1, pb, (unsigned int) start+duration, t1); |
||
203 | accessfile(dbuf,"w","%s",vbuf); |
||
204 | accessfile(tbuf,"r","%s/%s/.E%d",class_base,pc,t1); |
||
205 | if(strchr(tbuf,'#')==NULL && strcmp(pu,"supervisor")!=0) { /* not for simulation */ |
||
206 | snprintf(tbuf,sizeof(tbuf),"%d 00 %d %u %s %s %s\n", |
||
207 | t1, duration/60, (unsigned int) start,p1,pb, |
||
208 | nowstr); |
||
209 | if(prime!=0) { |
||
12287 | bpr | 210 | int n=strlen(tbuf); |
7673 | bpr | 211 | snprintf(tbuf+n,sizeof(tbuf)-n,"%d %.2f -1 %u %s %s\n", |
212 | t1,prime,(unsigned int) start,p1,pb); |
||
12287 | bpr | 213 | } |
214 | accessfile(tbuf,"a","%s/%s/score/%s.exam", |
||
7673 | bpr | 215 | class_base,pc,pu); |
12245 | bpr | 216 | } |
217 | else accessfile("yes","w","%s/%s/examsimu.%d", |
||
7673 | bpr | 218 | session_dir,pb,t1); |
12245 | bpr | 219 | } |
17457 | guerimand | 220 | /* set up wims_scoring + wims_time_remain */ |
221 | if(pc==NULL) pc=getvar("wims_class"); |
||
17459 | guerimand | 222 | remain=duration+start-nowtime; |
17457 | guerimand | 223 | if(pc) { |
224 | int maxremain; |
||
225 | maxremain=getscorestatus(pc,t1); |
||
17459 | guerimand | 226 | /* negative return is score retriction timeleft */ |
17465 | guerimand | 227 | if (maxremain<0 && -maxremain < remain) { |
228 | remain=-maxremain; |
||
229 | } |
||
230 | snprintf(vbuf,sizeof(vbuf),"%s/%s/examdepend.%d",session_dir,pb,t1); |
||
231 | snprintf(dbuf,sizeof(dbuf),"%u",(unsigned int) nowtime+remain); |
||
232 | accessfile(dbuf,"w","%s",vbuf); |
||
233 | } |
||
17457 | guerimand | 234 | if(remain<0) remain=0; |
12245 | bpr | 235 | snprintf(dbuf,sizeof(dbuf),"%d",remain); |
17457 | guerimand | 236 | setvar("wims_exam_remain",dbuf); |
10 | reyssat | 237 | } |
238 | |||
239 | double currexamscore(int sh) |
||
240 | { |
||
12245 | bpr | 241 | char buf[MAX_FNAME+1], sbuf[MAX_LINELEN+1]; |
242 | char *p, *p1, *cl; |
||
243 | int i, excnt; |
||
244 | double sc, w, ww, prime; |
||
7673 | bpr | 245 | |
12245 | bpr | 246 | cl=getvar("wims_class"); if(cl==NULL || *cl==0) return 0; |
247 | mystrncpy(sbuf,session_prefix,sizeof(sbuf)); |
||
248 | p=strstr(sbuf,"_exam"); if(p) *p=0; |
||
249 | accessfile(buf,"r","%s/examdata.%d",sbuf,sh); |
||
250 | p=find_word_start(find_word_end(find_word_start(buf))); |
||
251 | if(*p) prime=atof(p); else prime=0; |
||
252 | exam_currscore(sh); |
||
253 | snprintf(buf,sizeof(buf),"%s/%s/exams/.exam%d",class_base,cl,sh); |
||
254 | direct_datafile=1; |
||
255 | excnt=datafile_recordnum(buf); |
||
13168 | bpr | 256 | w=sc=0; |
257 | for(i=0;i<excnt;i++) { |
||
12245 | bpr | 258 | sbuf[0]=0; datafile_fnd_record(buf,i+1,sbuf); |
259 | p1=find_word_start(sbuf); *find_word_end(p1)=0; |
||
260 | ww=atof(p1); if(ww<=0) continue; |
||
261 | w+=ww; if(exam_scoredata[i]>-1000) sc+=exam_scoredata[i]*ww; |
||
262 | } |
||
263 | direct_datafile=0; if(sc<0) sc=0; |
||
264 | if(w==0) return 0; else return (1-prime/10)*sc/w+prime; |
||
10 | reyssat | 265 | } |
266 | |||
267 | void calc_examdep(char *p) |
||
268 | { |
||
12245 | bpr | 269 | char *p1, *p2; |
270 | int t; |
||
271 | if(!trusted_module()) {abt: *p=0; return;} |
||
272 | p1=find_word_start(p); p2=find_word_end(p1); |
||
273 | if(*p2==0) goto abt; |
||
274 | *p2++=0; p2=find_word_start(p2); |
||
275 | t=atoi(p1); |
||
276 | snprintf(p,MAX_LINELEN, exam_depcheck(p2,t)? "yes" : "no"); |
||
10 | reyssat | 277 | } |