Rev 3842 | Rev 8185 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3842 | Rev 7673 | ||
---|---|---|---|
Line 15... | Line 15... | ||
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
16 | */ |
16 | */ |
17 | 17 | ||
18 | #include <utime.h> |
18 | #include <utime.h> |
19 | 19 | ||
20 |
|
20 | /* Subroutines to process examinations */ |
21 | 21 | ||
22 | char eparm[MAX_LINELEN+1]; |
22 | char eparm[MAX_LINELEN+1]; |
23 | 23 | ||
24 | void exam_parm(void) |
24 | void exam_parm(void) |
25 | { |
25 | { |
26 | char *p1, *p2, *p3; |
26 | char *p1, *p2, *p3; |
27 | int v; |
27 | int v; |
28 | setvar("module_init_parm",eparm); |
28 | setvar("module_init_parm",eparm); |
29 | for(v=0,p1=eparm; *p1; p1=p2) { |
29 | for(v=0,p1=eparm; *p1; p1=p2) { |
30 |
|
30 | while(*p1=='&') p1++; |
31 |
|
31 | p2=strchr(p1,'&'); |
32 |
|
32 | if(p2==NULL) p2=p1+strlen(p1); else *p2++=0; |
33 |
|
33 | p3=strchr(p1,'='); if(p3==NULL) continue; else *p3++=0; |
34 |
|
34 | p1=find_word_start(p1); *find_word_end(p1)=0; |
35 |
|
35 | p3=find_word_start(p3); strip_trailing_spaces(p3); |
36 |
|
36 | user_variable[v].name=p1; user_variable[v].value=p3; |
37 |
|
37 | v++; |
38 | } |
38 | } |
39 | user_var_no=v; |
39 | user_var_no=v; |
40 | } |
40 | } |
41 | 41 | ||
42 |
|
42 | /* prepare examination situation */ |
43 | void check_exam(void) |
43 | void check_exam(void) |
44 | { |
44 | { |
45 | char *p, *p2, *e1, *e2, *pc=NULL; |
45 | char *p, *p2, *e1, *e2, *pc=NULL; |
46 | char ps[64], pb[64], cbuf[64], dbuf[64], vbuf[MAX_FNAME+1]; |
46 | char ps[64], pb[64], cbuf[64], dbuf[64], vbuf[MAX_FNAME+1]; |
47 | int t1, t2; |
47 | int t1, t2; |
48 | int start, duration, remain; |
48 | int start, duration, remain; |
49 | double prime; |
49 | double prime; |
50 | struct stat st; |
50 | struct stat st; |
51 | 51 | ||
52 | p=getvar(ro_name[ro_session]); |
52 | p=getvar(ro_name[ro_session]); |
53 | if(p==NULL || (p2=strstr(p,"_exam"))==NULL) return; |
53 | if(p==NULL || (p2=strstr(p,"_exam"))==NULL) return; |
54 | mystrncpy(pb,p,sizeof(pb)); p=pb; |
54 | mystrncpy(pb,p,sizeof(pb)); p=pb; |
55 | p2=strstr(p,"_exam"); if(p2==NULL) return; else *p2=0; |
55 | p2=strstr(p,"_exam"); if(p2==NULL) return; else *p2=0; |
56 | 56 | ||
57 | if(strchr(p2+1,'t')==NULL) { |
57 | if(strchr(p2+1,'t')==NULL) { |
58 |
|
58 | e1=getvar(ro_name[ro_worksheet]); |
59 |
|
59 | if(e1==NULL || *e1==0) { |
60 |
|
60 | bad: user_error("bad_exam"); return; |
61 |
|
61 | } |
62 |
|
62 | e2=strchr(e1,'.'); if(e2==NULL) goto bad; |
63 |
|
63 | e2++; t1=atoi(e1); t2=atoi(e2); |
64 | } |
64 | } |
65 | else { |
65 | else { |
66 |
|
66 | char *pt1,*pt2; |
67 |
|
67 | pt1=strchr(p2+1,'t'); pt2=strchr(pt1+1,'t'); |
68 |
|
68 | *pt1++=0; *pt2++=0; t1=atoi(pt1); t2=atoi(pt2); |
69 | } |
69 | } |
70 | if(t1<1 || t1>99 || t2<1 || t2>99) goto bad; |
70 | if(t1<1 || t1>99 || t2<1 || t2>99) goto bad; |
71 | snprintf(ps,sizeof(ps),"%s_examt%dt%d",p,t1,t2); |
71 | snprintf(ps,sizeof(ps),"%s_examt%dt%d",p,t1,t2); |
72 | isexam=1; setsesdir(ps); force_setvar("wims_isexam","1"); |
72 | isexam=1; setsesdir(ps); force_setvar("wims_isexam","1"); |
73 | force_setvar(ro_name[ro_session],ps); |
73 | force_setvar(ro_name[ro_session],ps); |
74 |
|
74 | /* get exam setup data */ |
75 | accessfile(cbuf,"r","%s/%s/examdata.%d", session_dir,pb,t1); |
75 | accessfile(cbuf,"r","%s/%s/examdata.%d", session_dir,pb,t1); |
76 | if(cbuf[0]==0) goto bad; |
76 | if(cbuf[0]==0) goto bad; |
77 | p=find_word_start(cbuf); p2=find_word_end(p); if(*p2) *p2++=0; |
77 | p=find_word_start(cbuf); p2=find_word_end(p); if(*p2) *p2++=0; |
78 | duration=atoi(p)*60; if(duration==0) goto bad; |
78 | duration=atoi(p)*60; if(duration==0) goto bad; |
79 | if(*p2) prime=atof(p2); else prime=0; |
79 | if(*p2) prime=atof(p2); else prime=0; |
80 | if (strstr(ps,parent_dir_string)!=NULL) user_error("wrong_session"); |
80 | if (strstr(ps,parent_dir_string)!=NULL) user_error("wrong_session"); |
81 |
|
81 | /* Whether the exercise is already done */ |
82 | p=getvar(ro_name[ro_cmd]); if(p!=NULL) { |
82 | p=getvar(ro_name[ro_cmd]); if(p!=NULL) { |
83 |
|
83 | if(strcmp(p,"getins")==0 || strcmp(p,"getframe")==0) goto skipped; |
84 | } |
84 | } |
85 | exam_currscore(t1); |
85 | exam_currscore(t1); |
86 | if(exam_scoredata[t2-1]!=-1000) { |
86 | if(exam_scoredata[t2-1]!=-1000) { |
87 |
|
87 | snprintf(dbuf,sizeof(dbuf),"%.1f",exam_scoredata[t2-1]); |
88 |
|
88 | setvar("wims_exo_lastscore",dbuf); |
89 |
|
89 | /* Do we need to erase subsession? */ |
90 |
|
90 | user_error("exam_exo_finished"); |
91 | } |
91 | } |
92 | skipped: |
92 | skipped: |
93 | snprintf(session_prefix,sizeof(session_prefix),"%s/%s",session_dir,ps); |
93 | snprintf(session_prefix,sizeof(session_prefix),"%s/%s",session_dir,ps); |
94 | snprintf(vbuf,sizeof(vbuf),"%s/var",session_prefix); |
94 | snprintf(vbuf,sizeof(vbuf),"%s/var",session_prefix); |
95 | if(stat(vbuf,&st)==0) { |
95 | if(stat(vbuf,&st)==0) { /* exists */ |
96 |
|
96 | unsetvar("module"); |
97 |
|
97 | p=getvar(ro_name[ro_cmd]); |
98 |
|
98 | if(p==NULL) { |
99 |
|
99 | recmd: |
100 |
|
100 | force_setvar(ro_name[ro_cmd],commands[cmd_resume]); |
101 |
|
101 | user_var_no=0; |
102 |
|
102 | } |
103 |
|
103 | else { |
104 |
|
104 | int i; |
105 |
|
105 | for(i=0;i<CMD_NO && strcmp(p,commands[i]);i++); |
106 |
|
106 | if(i>=CMD_NO || i==cmd_intro || i==cmd_new || i==cmd_renew || i==cmd_hint) |
107 |
|
107 | goto recmd; |
108 |
|
108 | } |
109 | } |
109 | } |
110 | else { |
110 | else { /* new */ |
111 |
|
111 | char *pt, cbuf[MAX_FNAME+1], ebuf[MAX_FNAME+1]; |
112 |
|
112 | char buf[2][MAX_LINELEN+1]; |
113 |
|
113 | int w1,w2; |
114 | 114 | ||
115 |
|
115 | force_setvar(ro_name[ro_cmd],commands[cmd_new]); |
116 |
|
116 | get_static_session_var(); |
117 | 117 | ||
118 |
|
118 | pc=getvar("wims_class"); if(pc==NULL) pc=""; |
119 |
|
119 | snprintf(cbuf,sizeof(cbuf),"%s/%s",class_base,pc); |
120 |
|
120 | snprintf(ebuf,sizeof(ebuf),"%s/exams/.exam%d",cbuf,t1); |
121 |
|
121 | direct_datafile=1; |
122 |
|
122 | datafile_fnd_record(ebuf,t2,buf[0]); |
123 |
|
123 | direct_datafile=0; |
124 |
|
124 | if(buf[0][0]==0) goto bad; |
125 |
|
125 | fnd_line(buf[0],4,buf[1]); if(buf[1][0]!=0) { /* dependencies */ |
126 |
|
126 | if(!exam_depcheck(buf[1],t1)) { |
127 | 127 | ||
128 |
|
128 | user_error("exam_dep"); |
129 |
|
129 | } |
130 |
|
130 | } |
131 |
|
131 | fnd_line(buf[0],2,buf[1]); if(buf[1][0]==0) goto bad; |
132 |
|
132 | calc_randitem(buf[1]); |
133 |
|
133 | pt=strchr(buf[1],'.'); if(pt==NULL) { |
134 |
|
134 | bad2: module_error("bad_exam_2"); return; |
135 |
|
135 | } |
136 |
|
136 | snprintf(exam_sheetexo,sizeof(exam_sheetexo)," %s",buf[1]); |
137 |
|
137 | *pt++=0; w1=atoi(buf[1]); w2=atoi(pt); |
138 |
|
138 | if(w1<1 || w1>99 || w2<1 || w2>99) goto bad2; |
139 |
|
139 | snprintf(ebuf,sizeof(ebuf),"%s/sheets/.sheet%d",cbuf,w1); |
140 |
|
140 | direct_datafile=1; |
141 |
|
141 | datafile_fnd_record(ebuf,w2,buf[0]); |
142 |
|
142 | direct_datafile=0; |
143 |
|
143 | if(buf[0][0]==0) goto bad2; |
144 |
|
144 | fnd_line(buf[0],1,buf[1]); if(buf[1][0]==0) goto bad2; |
145 |
|
145 | force_setvar(ro_name[ro_module],buf[1]); |
146 |
|
146 | fnd_line(buf[0],2,eparm); /* if(eparm[0]==0) goto bad2; */ |
147 |
|
147 | exam_parm(); |
148 | } |
148 | } |
149 |
|
149 | /* Register start time */ |
150 | snprintf(vbuf,sizeof(vbuf),"%s/%s/examreg.%d", |
150 | snprintf(vbuf,sizeof(vbuf),"%s/%s/examreg.%d", |
151 |
|
151 | session_dir,pb,t1); |
152 | if(stat(vbuf,&st)==0) { |
152 | if(stat(vbuf,&st)==0) { /* reg exists */ |
153 |
|
153 | char tbuf[MAX_LINELEN+1]; |
154 |
|
154 | struct utimbuf ut; |
155 |
|
155 | accessfile(tbuf,"r",vbuf); start=atoi(tbuf); |
156 |
|
156 | if(start<=nowtime-duration) { |
157 |
|
157 | user_error("expired_exam"); return; |
158 |
|
158 | } |
159 |
|
159 | /* refresh session times */ |
160 |
|
160 | ut.actime=ut.modtime=nowtime; |
161 |
|
161 | utime(mkfname(NULL,"%s/%s",session_dir,pb),&ut); |
162 | } |
162 | } |
163 | else { /* First time call: register starting time */ |
163 | else { /* First time call: register starting time */ |
164 |
|
164 | char *pu, *p1, tbuf[MAX_LINELEN+1]; |
165 |
|
165 | snprintf(dbuf,sizeof(dbuf),"%u",(unsigned int) nowtime); |
166 |
|
166 | accessfile(dbuf,"w","%s",vbuf); start=nowtime; |
167 |
|
167 | if(pc==NULL) pc=getvar("wims_class"); if(pc==NULL) pc=""; |
168 |
|
168 | pu=getvar("wims_user"); if(pu==NULL) pu=""; |
169 |
|
169 | snprintf(vbuf,sizeof(vbuf),"%s/%s/.parmreg", class_base, pc); |
170 |
|
170 | mkdirs(vbuf); |
171 |
|
171 | snprintf(vbuf,sizeof(vbuf),"%s/%s/.parmreg/%s.exam", |
172 |
|
172 | class_base, pc, pu); |
173 |
|
173 | p1=remote_addr; |
174 |
|
174 | snprintf(dbuf,sizeof(dbuf),"%s %s %u %d", |
175 |
|
175 | p1, pb, (unsigned int) start+duration, t1); |
176 |
|
176 | accessfile(dbuf,"w","%s",vbuf); |
177 |
|
177 | accessfile(tbuf,"r","%s/%s/.E%d",class_base,pc,t1); |
178 |
|
178 | if(strchr(tbuf,'#')==NULL && strcmp(pu,"supervisor")!=0) { /* not for simulation */ |
179 |
|
179 | snprintf(tbuf,sizeof(tbuf),"%d 00 %d %u %s %s %s\n", |
180 |
|
180 | t1, duration/60, (unsigned int) start,p1,pb, |
181 |
|
181 | nowstr); |
182 |
|
182 | if(prime!=0) { |
183 |
|
183 | int n=strlen(tbuf); |
184 |
|
184 | snprintf(tbuf+n,sizeof(tbuf)-n,"%d %.2f -1 %u %s %s\n", |
185 |
|
185 | t1,prime,(unsigned int) start,p1,pb); |
186 |
|
186 | } |
187 |
|
187 | accessfile(tbuf,"a","%s/%s/score/%s.exam", |
188 |
|
188 | class_base,pc,pu); |
189 |
|
189 | } |
190 |
|
190 | else accessfile("yes","w","%s/%s/examsimu.%d", |
191 |
|
191 | session_dir,pb,t1); |
192 | } |
192 | } |
193 | remain=duration+start-nowtime; if(remain<0) remain=0; |
193 | remain=duration+start-nowtime; if(remain<0) remain=0; |
194 | snprintf(dbuf,sizeof(dbuf),"%d",remain); |
194 | snprintf(dbuf,sizeof(dbuf),"%d",remain); |
195 | setvar("wims_exam_remain",dbuf); |
195 | setvar("wims_exam_remain",dbuf); /* remaining time in seconds */ |
196 | if(pc==NULL) pc=getvar("wims_class"); |
196 | if(pc==NULL) pc=getvar("wims_class"); |
197 | if(pc) getscorestatus(pc,t1); |
197 | if(pc) getscorestatus(pc,t1); /* set up wims_scoring */ |
198 | } |
198 | } |
199 | 199 | ||
200 | double currexamscore(int sh) |
200 | double currexamscore(int sh) |
201 | { |
201 | { |
202 | char buf[MAX_FNAME+1], sbuf[MAX_LINELEN+1]; |
202 | char buf[MAX_FNAME+1], sbuf[MAX_LINELEN+1]; |
203 | char *p, *p1, *cl; |
203 | char *p, *p1, *cl; |
204 | int i, excnt; |
204 | int i, excnt; |
205 | double sc, w, ww, prime; |
205 | double sc, w, ww, prime; |
206 | 206 | ||
207 | cl=getvar("wims_class"); if(cl==NULL || *cl==0) return 0; |
207 | cl=getvar("wims_class"); if(cl==NULL || *cl==0) return 0; |
208 | mystrncpy(sbuf,session_prefix,sizeof(sbuf)); |
208 | mystrncpy(sbuf,session_prefix,sizeof(sbuf)); |
209 | p=strstr(sbuf,"_exam"); if(p) *p=0; |
209 | p=strstr(sbuf,"_exam"); if(p) *p=0; |
210 | accessfile(buf,"r","%s/examdata.%d",sbuf,sh); |
210 | accessfile(buf,"r","%s/examdata.%d",sbuf,sh); |
211 | p=find_word_start(find_word_end(find_word_start(buf))); |
211 | p=find_word_start(find_word_end(find_word_start(buf))); |
Line 213... | Line 213... | ||
213 | exam_currscore(sh); |
213 | exam_currscore(sh); |
214 | snprintf(buf,sizeof(buf),"%s/%s/exams/.exam%d",class_base,cl,sh); |
214 | snprintf(buf,sizeof(buf),"%s/%s/exams/.exam%d",class_base,cl,sh); |
215 | direct_datafile=1; |
215 | direct_datafile=1; |
216 | excnt=datafile_recordnum(buf); |
216 | excnt=datafile_recordnum(buf); |
217 | w=sc=0; for(i=0;i<excnt;i++) { |
217 | w=sc=0; for(i=0;i<excnt;i++) { |
218 |
|
218 | sbuf[0]=0; datafile_fnd_record(buf,i+1,sbuf); |
219 |
|
219 | p1=find_word_start(sbuf); *find_word_end(p1)=0; |
220 |
|
220 | ww=atof(p1); if(ww<=0) continue; |
221 |
|
221 | w+=ww; if(exam_scoredata[i]>-1000) sc+=exam_scoredata[i]*ww; |
222 | } |
222 | } |
223 | direct_datafile=0; if(sc<0) sc=0; |
223 | direct_datafile=0; if(sc<0) sc=0; |
224 | if(w==0) return 0; else return (1-prime/10)*sc/w+prime; |
224 | if(w==0) return 0; else return (1-prime/10)*sc/w+prime; |
225 | } |
225 | } |
226 | 226 |