Rev 18091 | Go to most recent revision | 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 | |||
8155 | bpr | 18 | /* Routines treating user scores. */ |
8185 | bpr | 19 | #include "wims.h" |
10 | reyssat | 20 | |
7149 | bpr | 21 | double oldfactor=0.85; /* quality factor, should remain stable. */ |
10 | reyssat | 22 | |
12222 | bpr | 23 | enum {sr_require, sr_weight, sr_score, sr_mean, sr_remain, |
12273 | bpr | 24 | sr_last, sr_try, sr_best, sr_level, sr_new, sr_seedlast, sr_seedscorelast, |
12295 | bpr | 25 | sr_seedscores, sr_seedlastcnt}; |
10 | reyssat | 26 | char scorebuf[MAX_CLASSEXOS*sizeof(scoreresult)+32]; |
27 | struct scoreresult *rscore; |
||
28 | int scorecnt; |
||
29 | double scoresum[MAX_SHEETS]; |
||
30 | int sheetstart[MAX_SHEETS], shexocnt[MAX_SHEETS]; |
||
31 | int examstart, examcnt; |
||
32 | char rscore_class[MAX_CLASSLEN+1]; |
||
33 | char rscore_user[MAX_NAMELEN+1]; |
||
34 | |||
35 | int totsheets=0; |
||
36 | int score_ispublic=0; |
||
7149 | bpr | 37 | int score_status=-1; /* save of score status */ |
10 | reyssat | 38 | int score_statussheet=-1; |
39 | int score_statusisexam=-1; |
||
40 | double scorerecfactor=0.9; |
||
41 | |||
12197 | bpr | 42 | /* gather user score, core routine. |
43 | rscore data is created (table of structures). |
||
44 | according to the value of wims_sheet or wims_exo |
||
45 | */ |
||
10 | reyssat | 46 | int getscoreuser(char *classe, char *user) |
47 | { |
||
15847 | bpr | 48 | int i, osh, sh; |
7407 | bpr | 49 | char *nowuser, *nowsheet, *nowexo, *nowscore; |
50 | char *pp; |
||
12196 | bpr | 51 | if(user==NULL || *user==0) { |
7407 | bpr | 52 | user=getvar("wims_user"); |
53 | if(user==NULL || *user==0) return -1; |
||
54 | } |
||
55 | if(strcmp(classe,rscore_class)==0 && strcmp(user,rscore_user)==0) return 0; |
||
56 | nowsheet=nowexo=nowscore=""; |
||
12495 | bpr | 57 | nowuser=getvar("wims_user"); |
58 | if(nowuser!=NULL && strcmp(user,nowuser)==0) { |
||
12196 | bpr | 59 | nowscore=getvar("module_score"); |
60 | if(nowscore!=NULL && *nowscore!=0) { |
||
61 | nowsheet=getvar("wims_sheet"); |
||
62 | if(nowsheet==NULL) nowsheet=""; |
||
63 | nowexo=getvar("wims_exo"); |
||
64 | if(nowexo==NULL) nowexo=""; |
||
10 | reyssat | 65 | } |
7407 | bpr | 66 | else nowscore=""; |
67 | } |
||
68 | snprintf(scorebuf+sizeof(int),sizeof(scorebuf)-sizeof(int), |
||
7646 | bpr | 69 | "-c%s -u%s getscore %s %s %s", |
70 | classe,user,nowsheet,nowexo,nowscore); |
||
71 | i=kerneld(scorebuf,sizeof(scorebuf)); |
||
72 | if(i<0) internal_error("getscoreuser(): daemon failure."); |
||
7407 | bpr | 73 | if(memcmp(scorebuf+sizeof(int),"OK",2)!=0) { |
74 | if(memcmp(scorebuf+sizeof(int),"ERROR",5)==0) { |
||
75 | module_error(find_word_start(scorebuf+sizeof(int)+8)); |
||
10 | reyssat | 76 | } |
7407 | bpr | 77 | else internal_error("getscoreuser(): communication error with wimslogd."); |
78 | } |
||
8340 | bpr | 79 | /* 3 is here the length of "OK " */ |
7407 | bpr | 80 | pp=scorebuf+sizeof(int)+3; rscore=(struct scoreresult *) pp; |
81 | scorecnt=(i-sizeof(int)-3)/sizeof(scoreresult); |
||
82 | if(scorecnt>MAX_CLASSEXOS) module_error("too_many_exercises"); |
||
15847 | bpr | 83 | osh=-1; |
84 | for(i=totsheets=0;i<scorecnt;i++) { |
||
85 | sh=rscore[i].sh; |
||
86 | if (sh >= MAX_SHEETS) break; |
||
87 | while(osh<sh) |
||
88 | {++osh; scoresum[osh]=shexocnt[osh]=0; sheetstart[osh]=i;} |
||
89 | scoresum[sh]+=rscore[i].require*rscore[i].weight*rscore[i].active; |
||
90 | shexocnt[sh]++; |
||
7407 | bpr | 91 | } |
15847 | bpr | 92 | totsheets=osh+1; |
93 | |||
94 | examstart=i; examcnt=scorecnt-examstart; |
||
7407 | bpr | 95 | mystrncpy(rscore_class,classe,sizeof(rscore_class)); |
96 | mystrncpy(rscore_user,user,sizeof(rscore_user)); |
||
97 | return 0; |
||
10 | reyssat | 98 | } |
7602 | bpr | 99 | /* work : exo */ |
10 | reyssat | 100 | char *scorepname[]={ |
12222 | bpr | 101 | "class","user","sheet","work","exam" |
10 | reyssat | 102 | }; |
103 | #define scorepname_no (sizeof(scorepname)/sizeof(scorepname[0])) |
||
104 | char score_class[MAX_CLASSLEN+1]; |
||
18153 | bpr | 105 | int score_sheet,score_exo,score_isexam,score_exam; |
10 | reyssat | 106 | char score_user[256]; |
107 | |||
7407 | bpr | 108 | /* Uniformed treatment of score command parameters |
109 | * format: class=? user=? sheet=? work=? |
||
8155 | bpr | 110 | * all are optional. |
111 | */ |
||
10 | reyssat | 112 | void _scoreparm(char *p) |
113 | { |
||
114 | int i; |
||
115 | char *pn, *pe, *pd, *pf; |
||
116 | char sav; |
||
7407 | bpr | 117 | |
18153 | bpr | 118 | score_sheet=score_exo=score_isexam=score_exam=score_ispublic=0; *score_class=0; |
10 | reyssat | 119 | score_user[0]=0; |
120 | for(i=0;i<scorepname_no;i++) { |
||
16749 | bpr | 121 | pf=p; |
122 | ahead: |
||
123 | pn=strstr(pf,scorepname[i]); pf=pn+1; |
||
124 | if(pn==NULL) continue; |
||
125 | if(pn>p && !isspace(*(pn-1))) goto ahead; |
||
126 | pe=find_word_start(pn+strlen(scorepname[i])); |
||
127 | if(*pe!='=') goto ahead; |
||
128 | pd=find_word_start(pe+1); |
||
129 | pf=find_word_end(pd); |
||
130 | if(pf<=pd) continue; |
||
131 | sav=*pf; *pf=0; |
||
132 | switch(i) { |
||
133 | case 0: /* class */ |
||
134 | mystrncpy(score_class,pd,sizeof(score_class)); break; |
||
135 | case 1: /* user */ |
||
136 | mystrncpy(score_user,pd,sizeof(score_user)); break; |
||
137 | case 2: { /* sheet */ |
||
7149 | bpr | 138 | if(*pd=='P') {pd++; score_ispublic=1;} |
139 | score_sheet=atoi(pd); |
||
140 | break; |
||
16749 | bpr | 141 | } |
142 | case 3: /* work=exo */ |
||
143 | score_exo=atoi(pd); break; |
||
144 | case 4: /* exam */ |
||
18153 | bpr | 145 | score_isexam=1;score_exam=atoi(pd); break; |
7149 | bpr | 146 | } |
147 | *pf=sav; ovlstrcpy(pn, pf); |
||
10 | reyssat | 148 | } |
149 | *p=0; |
||
16749 | bpr | 150 | /* the commands are OK from a non trusted module if the user and the |
151 | class are not precised, so it can be only the user in his class */ |
||
10 | reyssat | 152 | if((*score_class!=0 || score_user[0]!=0) && !trusted_module()) { |
16749 | bpr | 153 | module_error("not_trusted"); return; |
10 | reyssat | 154 | } |
155 | if(*score_class==0) { |
||
16749 | bpr | 156 | char *classe; |
157 | classe=getvar("wims_class"); |
||
158 | if(classe==NULL || *classe==0) return; |
||
159 | else mystrncpy(score_class,classe,sizeof(score_class)); |
||
10 | reyssat | 160 | } |
161 | if(score_user[0]==0) { |
||
7149 | bpr | 162 | char *user; |
163 | user=getvar("wims_user"); |
||
164 | if(user!=NULL) mystrncpy(score_user,user,sizeof(score_user)); |
||
10 | reyssat | 165 | } |
166 | } |
||
167 | |||
7407 | bpr | 168 | /* gather score: relatif to some of the |
169 | * user class work sheet exam |
||
8155 | bpr | 170 | * dtype can be require weight score mean remain best last level try |
7407 | bpr | 171 | */ |
172 | |||
10 | reyssat | 173 | void _getscore(char *p,int dtype) |
174 | { |
||
12222 | bpr | 175 | int i,sh,ex,osh; |
176 | float d; |
||
12273 | bpr | 177 | char dc[SEEDSIZE]; |
178 | char ds[SEEDSCORES]; |
||
12222 | bpr | 179 | char *p1; |
10 | reyssat | 180 | |
12222 | bpr | 181 | _scoreparm(p); |
182 | if(*score_class==0 || *score_user==0) return; |
||
183 | if(getscoreuser(score_class,score_user)<0) return; |
||
184 | for(i=osh=0,p1=p;i<scorecnt && p1-p<MAX_LINELEN-32;i++) { |
||
15847 | bpr | 185 | sh=rscore[i].sh+1; if(sh<1 || sh>MAX_SHEETS) break; |
12222 | bpr | 186 | if(score_sheet!=0) { |
187 | if(sh<score_sheet) continue; |
||
188 | if(sh>score_sheet || sh>MAX_SHEETS) break; |
||
189 | } |
||
15847 | bpr | 190 | ex=rscore[i].exo+1; |
12222 | bpr | 191 | if(score_exo!=0 && ex!=score_exo) continue; |
192 | if(osh!=0 && sh!=osh) *p1++='\n'; |
||
193 | switch(dtype) { |
||
194 | case sr_require: {d=rscore[i].require; break;} |
||
195 | case sr_weight: {d=rscore[i].weight; break;} |
||
196 | case sr_score: {d=rscore[i].score; break;} |
||
197 | case sr_mean: {d=rscore[i].mean; break;} |
||
198 | case sr_remain: {d=rscore[i].require-rscore[i].score; break;} |
||
199 | case sr_last: {d=rscore[i].last; break;} |
||
200 | case sr_try: {d=rscore[i].try; break;} |
||
12230 | bpr | 201 | case sr_new: {d=rscore[i].new; break;} |
12222 | bpr | 202 | case sr_best: {d=rscore[i].best; break;} |
12273 | bpr | 203 | case sr_level: {d=rscore[i].level; break;} |
204 | case sr_seedscorelast: {d=rscore[i].seedscorelast; break;} |
||
12295 | bpr | 205 | case sr_seedlastcnt: {d=rscore[i].seedlastcnt; break;} |
12273 | bpr | 206 | case sr_seedlast: { mystrncpy(dc,rscore[i].seedlast,SEEDSIZE); |
207 | break; |
||
208 | } |
||
209 | case sr_seedscores: { |
||
210 | mystrncpy(ds,rscore[i].seedscores,SEEDSCORES); break; |
||
211 | } |
||
12222 | bpr | 212 | default: {d=0; break;} |
213 | } |
||
12273 | bpr | 214 | switch(dtype) { |
215 | case sr_seedlast: |
||
216 | { snprintf(p1,SEEDSIZE, "%s", dc); p1+=strlen(p1); break; } |
||
217 | case sr_seedscores: |
||
218 | { snprintf(p1,SEEDSCORES, "%s", ds); p1+=strlen(p1); break; } |
||
219 | default: |
||
220 | { p1=moneyprint(p1,d); } |
||
221 | } |
||
222 | *p1++=' '; |
||
12222 | bpr | 223 | osh=sh; |
224 | } |
||
225 | *p1++='\n'; *p1=0; |
||
10 | reyssat | 226 | } |
227 | |||
7407 | bpr | 228 | /* gather user score. */ |
10 | reyssat | 229 | void calc_getscore(char *p) |
230 | { |
||
7407 | bpr | 231 | _getscore(p,sr_score); |
10 | reyssat | 232 | } |
233 | |||
7407 | bpr | 234 | /* gather user score average. */ |
10 | reyssat | 235 | void calc_getscoremean(char *p) |
236 | { |
||
7407 | bpr | 237 | _getscore(p,sr_mean); |
10 | reyssat | 238 | } |
239 | |||
7407 | bpr | 240 | /* gather remaining of score to get for user. */ |
10 | reyssat | 241 | void calc_getscoreremain(char *p) |
242 | { |
||
7407 | bpr | 243 | _getscore(p,sr_remain); |
10 | reyssat | 244 | } |
245 | |||
7407 | bpr | 246 | /* Require score table. */ |
10 | reyssat | 247 | void calc_getscorerequire(char *p) |
248 | { |
||
7407 | bpr | 249 | _getscore(p,sr_require); |
10 | reyssat | 250 | } |
251 | |||
7407 | bpr | 252 | /* Score weight table. */ |
10 | reyssat | 253 | void calc_getscoreweight(char *p) |
254 | { |
||
7407 | bpr | 255 | _getscore(p,sr_weight); |
10 | reyssat | 256 | } |
14126 | obado | 257 | /* user last score */ |
7602 | bpr | 258 | void calc_getscorelast(char *p) |
259 | { |
||
260 | _getscore(p,sr_last); |
||
261 | } |
||
12196 | bpr | 262 | /* gather user score try numbers with score activated. */ |
7602 | bpr | 263 | void calc_getscoretry(char *p) |
264 | { |
||
265 | _getscore(p,sr_try); |
||
266 | } |
||
12220 | bpr | 267 | /* gather all user try numbers (terminated or not, but with notation activated)*/ |
12197 | bpr | 268 | void calc_getscorealltries(char *p) |
12196 | bpr | 269 | { |
12230 | bpr | 270 | _getscore(p,sr_new); |
12196 | bpr | 271 | } |
7602 | bpr | 272 | |
7657 | bpr | 273 | /* if the required points are 10* N, gather N user best scores */ |
7638 | bpr | 274 | void calc_getscorebest(char *p) |
275 | { |
||
276 | _getscore(p,sr_best); |
||
277 | } |
||
278 | |||
7657 | bpr | 279 | /* gather user score average. */ |
280 | void calc_getscorelevel(char *p) |
||
281 | { |
||
282 | _getscore(p,sr_level); |
||
283 | } |
||
284 | |||
7638 | bpr | 285 | /* percentage of work done for each sheet: |
7657 | bpr | 286 | * score mean best level |
287 | * as follows |
||
14126 | obado | 288 | * score=100*cumulative_points/required_points (< 100) |
7665 | bpr | 289 | * mean=quality (<10) |
290 | * best=10*(required/10 best_scores)/required_points (< 100) |
||
14134 | obado | 291 | * level=minimum of the required/10 best_scores (< 100) |
7638 | bpr | 292 | */ |
7657 | bpr | 293 | |
294 | void calc_getscorepercent(char *p) |
||
10 | reyssat | 295 | { |
7407 | bpr | 296 | int i,j,jend; |
7657 | bpr | 297 | double tot, mean, totb, totl, totw, d; |
7407 | bpr | 298 | char *p1; |
10 | reyssat | 299 | |
7407 | bpr | 300 | _scoreparm(p); |
301 | if(*score_class==0 || *score_user==0) return; |
||
302 | if(getscoreuser(score_class,score_user)<0) return; |
||
303 | for(p1=p,i=0;i<totsheets && p1-p<MAX_LINELEN-32;i++) { |
||
304 | if(scoresum[i]==0) { |
||
7657 | bpr | 305 | ovlstrcpy(p1,"0 0 0 0\n"); p1+=strlen(p1); continue; |
10 | reyssat | 306 | } |
7407 | bpr | 307 | if(score_sheet!=0 && i!=score_sheet-1) continue; |
308 | if(scoresum[i]<=0) *p1++='\n'; |
||
7657 | bpr | 309 | tot=mean=totb=totl=totw=0; jend=sheetstart[i]+shexocnt[i]; |
7407 | bpr | 310 | for(j=sheetstart[i];j<jend;j++) { |
12495 | bpr | 311 | /* if mean<1 then ignore score. |
312 | * if mean<2 then half score. |
||
313 | */ |
||
7407 | bpr | 314 | if(rscore[j].mean>=1) { |
7646 | bpr | 315 | double dt=rscore[j].score; |
316 | float db=rscore[j].best; |
||
7657 | bpr | 317 | float dl=rscore[j].level; |
318 | if(rscore[j].mean<2) {dt=dt/2; db=db/2; dl=dl/2;} |
||
15847 | bpr | 319 | d=dt*rscore[j].weight*rscore[j].active; |
320 | /* quality; barycenter with coefficients d */ |
||
7646 | bpr | 321 | mean+=rscore[j].mean*d; |
12495 | bpr | 322 | /* cumulative score */ |
7646 | bpr | 323 | tot+=d; |
12495 | bpr | 324 | /* best */ |
15847 | bpr | 325 | totb+=db*rscore[j].weight*rscore[j].active; |
12495 | bpr | 326 | /* level */ |
15847 | bpr | 327 | totl+=dl*rscore[j].weight*rscore[j].active; |
328 | totw+=rscore[j].weight*rscore[j].active; |
||
7407 | bpr | 329 | } |
330 | } |
||
7638 | bpr | 331 | if(tot>0) {d=mean/tot;} else d=0; |
12495 | bpr | 332 | /* cumulative score */ |
7407 | bpr | 333 | p1=moneyprint(p1,rint(100*tot/scoresum[i])); *p1++=' '; |
12495 | bpr | 334 | /* quality */ |
7638 | bpr | 335 | p1=moneyprint(p1,d); *p1++=' '; |
12495 | bpr | 336 | /* best */ |
7657 | bpr | 337 | p1=moneyprint(p1,rint(100*totb/scoresum[i])); *p1++=' '; |
12495 | bpr | 338 | /* level */ |
7657 | bpr | 339 | p1=moneyprint(p1,rint(10*totl/totw)); |
340 | |||
341 | *p1++='\n'; |
||
7407 | bpr | 342 | } |
343 | *p1=0; |
||
10 | reyssat | 344 | } |
12273 | bpr | 345 | /* [seed1,score1;seed2,score2;...] at most MAX_SCORESEED */ |
346 | void calc_getseedscores(char *p) |
||
347 | { |
||
348 | _getscore(p,sr_seedscores); |
||
349 | } |
||
350 | /* last seed (0 if there is no seed)*/ |
||
351 | void calc_getseedlast(char *p) |
||
352 | { |
||
353 | _getscore(p,sr_seedlast); |
||
354 | } |
||
355 | /* last score (-1 if does not exist) */ |
||
356 | void calc_getseedscorelast(char *p) |
||
357 | { |
||
358 | _getscore(p,sr_seedscorelast); |
||
359 | } |
||
10 | reyssat | 360 | |
12295 | bpr | 361 | /* number of occurences of the last seed */ |
362 | void calc_getseedlastcnt(char *p) |
||
363 | { |
||
364 | _getscore(p,sr_seedlastcnt); |
||
365 | } |
||
366 | |||
7407 | bpr | 367 | /* Returns the status of a sheet, or -1 if error */ |
10 | reyssat | 368 | int getsheetstatus(char *classe, int sheet) |
369 | { |
||
7407 | bpr | 370 | char *p, *st, buf[MAX_LINELEN+1], namebuf[MAX_FNAME+1]; |
18087 | bpr | 371 | int i,j,res,lnb; |
372 | char *p1,buf1[MAX_LINELEN],buf2[MAX_LINELEN]; |
||
373 | char buf3[MAX_LINELEN],buf4[MAX_LINELEN]; |
||
374 | if(isexam || score_isexam) {st="exam"; lnb=8;} else {st="sheet";lnb=9;}; |
||
7407 | bpr | 375 | mkfname(namebuf,"%s/%s/%ss/.%ss",class_base,classe,st,st); |
376 | direct_datafile=1;datafile_fnd_record(namebuf,sheet,buf);direct_datafile=0; |
||
377 | p=find_word_start(buf); if(*p==0) return -1; |
||
378 | i=*p-'0'; if(i>5 || i<0) i=-1; |
||
379 | if((isexam || score_isexam) && i==0) { |
||
380 | p=getvar("wims_user"); if(p!=NULL && strcmp(p,"supervisor")==0) i=1; |
||
381 | } |
||
18081 | bpr | 382 | res=i; |
383 | if (res == 0 || res > 2) |
||
384 | goto ret; |
||
385 | if (strcmp(score_user,"supervisor")==0 || score_user[0]==0) |
||
386 | goto ret; |
||
18087 | bpr | 387 | fnd_line(buf,lnb,buf1); |
388 | rows2lines(buf1); |
||
18085 | bpr | 389 | mkfname(namebuf,"%s/%s/.users/%s",class_base,classe,score_user); |
18081 | bpr | 390 | for(i=1;;++i){ |
18087 | bpr | 391 | fnd_line(buf1,i,buf); |
18081 | bpr | 392 | if(*buf==0) break; |
393 | for (j=1;;++j){ |
||
18087 | bpr | 394 | fnd_item(buf,j,buf2); |
395 | if (buf2[0]==0) {res = 3; goto ret;} |
||
396 | p1=strchr(buf2,'='); |
||
18081 | bpr | 397 | if(p1==NULL) break; |
398 | *p1=0; |
||
18087 | bpr | 399 | snprintf(buf3,sizeof(buf3),"%s_%s","user_techvar",buf2); |
400 | getdef(namebuf,buf3,buf4); |
||
401 | if(strcmp(buf4,p1+1)) break; |
||
18081 | bpr | 402 | } |
403 | } |
||
404 | ret: |
||
405 | return res; |
||
10 | reyssat | 406 | } |
407 | |||
13011 | bpr | 408 | /* return 1 if a word of bf2 is a substring of host |
409 | and if time restrictions are verified for wims_user |
||
8155 | bpr | 410 | * Content of bf2 is destroyed. |
411 | */ |
||
10303 | guerimand | 412 | int _subword(char bf2[],char *ftbuf) |
10 | reyssat | 413 | { |
7407 | bpr | 414 | char *p1, *p2; |
415 | for(p1=strchr(bf2,'\\'); p1!=NULL; p1=strchr(p1+1,'\\')) { |
||
416 | char buf[MAX_LINELEN+1], buf2[MAX_LINELEN+1], fbuf[MAX_FNAME+1]; |
||
417 | char *classp, *classp2, *userp, *scp; |
||
418 | classp=getvar("wims_class"); userp=getvar("wims_user"); |
||
419 | if(classp==NULL || userp==NULL || *classp==0 || *userp==0) break; |
||
420 | scp=getvar("wims_superclass"); |
||
421 | if(scp!=NULL && *scp!=0) classp2=scp; else classp2=classp; |
||
422 | if(p1>bf2 && !isspace(*(p1-1))) continue; |
||
423 | if(!isalnum(*(p1+1))) continue; |
||
424 | p2=find_word_end(p1); if(p2>=p1+MAX_NAMELEN) continue; |
||
425 | memmove(buf2, p1+1, p2-p1-1); buf2[p2-p1-1]=0; |
||
18081 | bpr | 426 | /* get value of technical variable for user */ |
10303 | guerimand | 427 | snprintf(buf,sizeof(buf),"user_techvar_%s",buf2); |
7407 | bpr | 428 | if(strcmp(userp,"supervisor")==0) |
429 | mkfname(fbuf,"%s/%s/supervisor",class_base,classp); |
||
430 | else |
||
431 | mkfname(fbuf,"%s/%s/.users/%s",class_base,classp2,userp); |
||
10303 | guerimand | 432 | getdef(fbuf,buf,buf2); |
18081 | bpr | 433 | /* end value for the user */ |
10365 | bpr | 434 | if(buf2[0]==0) ovlstrcpy(buf2,"EMPTY"); /* in case of no value defined for the user*/ |
10303 | guerimand | 435 | /* get time restriction for this value */ |
436 | snprintf(buf,sizeof(buf),"techvar_%s",buf2); |
||
13011 | bpr | 437 | /* mkfname(fbuf,"%s/%s/.E%s",class_base,classp,sheet); |
438 | * read time restriction corresponding to the value of |
||
439 | * technical variable in the file of the sheet or exam |
||
440 | */ |
||
10379 | bpr | 441 | getdef(ftbuf,buf,buf2); |
18081 | bpr | 442 | /* value for techvar */ |
10303 | guerimand | 443 | if(buf2[0]==0) ovlstrcpy(buf2,"none"); |
444 | /*string_modify(bf2,p1,p2,buf2);*/ |
||
445 | bf2=buf2; |
||
7407 | bpr | 446 | p1+=strlen(buf2); |
447 | } |
||
448 | if((isexam || score_isexam) && bf2[0]=='#') return 1; |
||
449 | if(wordchr(bf2,"none")!=NULL) return 0; |
||
450 | if(wordchr(bf2,"all")!=NULL) return 1; |
||
451 | p1=find_word_start(bf2); if(*p1==0) return 1; |
||
13011 | bpr | 452 | /* check host and time */ |
7407 | bpr | 453 | return checkhostt(p1); |
10 | reyssat | 454 | } |
455 | |||
13011 | bpr | 456 | /* Returns 1 if score registration is open for the user |
457 | * in variable wims_user, 0 otherwise. |
||
458 | */ |
||
10 | reyssat | 459 | int _getscorestatus(char *classe, int sheet) |
460 | { |
||
7407 | bpr | 461 | char nbuf[MAX_LINELEN+1], gbuf[MAX_LINELEN+1]; |
10303 | guerimand | 462 | char ftbuf[MAX_FNAME+1]=""; |
7407 | bpr | 463 | char *es; |
10 | reyssat | 464 | |
7407 | bpr | 465 | if(classe==NULL || *classe==0 || sheet<=0) return 1; |
466 | if(getsheetstatus(classe,sheet)!=1) return 0; |
||
467 | if(*remote_addr==0) return 0; |
||
468 | if(isexam || score_isexam) { /* exam simulation */ |
||
469 | accessfile(nbuf,"r","%s/%s/.E%d",class_base,classe,sheet); |
||
470 | if(nbuf[0]=='#') return 1; |
||
471 | } |
||
12814 | bpr | 472 | /* Global restriction data */ |
7407 | bpr | 473 | accessfile(nbuf,"r","%s/%s/.security",class_base,classe); |
474 | if(nbuf[0]) { |
||
475 | _getdef(nbuf,"allow",gbuf); |
||
10303 | guerimand | 476 | if(*find_word_start(gbuf)!=0 && _subword(gbuf,ftbuf)==0) |
7407 | bpr | 477 | return 0; |
478 | _getdef(nbuf,"except",gbuf); |
||
10303 | guerimand | 479 | if(*find_word_start(gbuf)!=0 && _subword(gbuf,ftbuf)==1) |
7407 | bpr | 480 | return 0; |
481 | } |
||
13011 | bpr | 482 | /* Sheet restriction data; take in account the technical variables */ |
7407 | bpr | 483 | if(isexam || score_isexam) es="E"; else es=""; |
484 | accessfile(nbuf,"r","%s/%s/.%s%d",class_base,classe,es,sheet); |
||
485 | if(*find_word_start(nbuf)==0) return 1; |
||
12814 | bpr | 486 | /* preparing score restriction file name :*/ |
10303 | guerimand | 487 | mkfname(ftbuf,"%s/%s/.%s%d",class_base,classe,es,sheet); |
488 | return _subword(nbuf,ftbuf); |
||
10 | reyssat | 489 | } |
490 | |||
13011 | bpr | 491 | /* Returns 1 if score registration is open for wims_user, 0 otherwise.*/ |
10 | reyssat | 492 | int getscorestatus(char *classe, int sheet) |
493 | { |
||
7407 | bpr | 494 | if(score_status<0 || score_statussheet!=sheet |
495 | || score_statusisexam!=isexam) { |
||
496 | score_statussheet=sheet; score_statusisexam=isexam; |
||
497 | score_status=_getscorestatus(classe,sheet); score_isexam=0; |
||
17457 | guerimand | 498 | if(score_status!=0 && (cmd_type==cmd_new || cmd_type==cmd_renew |
7646 | bpr | 499 | || isexam)) { |
7407 | bpr | 500 | char *p; |
501 | p=getvar("wims_scorereg"); |
||
502 | if(p==NULL || strcmp(p,"suspend")!=0) |
||
7646 | bpr | 503 | setvar("wims_scoring","pending"); |
7407 | bpr | 504 | else setvar("wims_scoring",""); |
10 | reyssat | 505 | } |
7407 | bpr | 506 | } |
507 | if(isexam && score_status==0) { |
||
508 | char *p; |
||
13557 | obado | 509 | p=getvar("wims_user"); |
510 | if(p==NULL || strcmp(p,"supervisor")!=0) |
||
511 | user_error("exam_closed"); |
||
7407 | bpr | 512 | } |
513 | return score_status; |
||
10 | reyssat | 514 | } |
515 | |||
7407 | bpr | 516 | /* Whether score registering is open */ |
10 | reyssat | 517 | void calc_getscorestatus(char *p) |
518 | { |
||
7407 | bpr | 519 | _scoreparm(p); |
520 | if(*score_class==0 || score_sheet==0 || *score_user==0) { |
||
521 | *p=0; return; |
||
522 | } |
||
523 | if(getscorestatus(score_class, score_sheet)) |
||
524 | ovlstrcpy(p,"yes"); |
||
525 | else ovlstrcpy(p,"no"); |
||
10 | reyssat | 526 | } |
527 | |||
18056 | bpr | 528 | /* get status of a sheet in a class: can be 0, 1, 2 or 3 |
18091 | bpr | 529 | (in preparation, active, expired or hidden) */ |
18056 | bpr | 530 | void calc_getsheetstatus(char *p) |
531 | { |
||
532 | _scoreparm(p); |
||
18087 | bpr | 533 | if(*score_class==0 || (score_sheet==0 && score_isexam==0)) { |
18056 | bpr | 534 | *p=0; return; |
535 | } |
||
18153 | bpr | 536 | snprintf(p,20,"%d",getsheetstatus(score_class, score_sheet?score_sheet:score_exam)); |
18056 | bpr | 537 | } |
538 | |||
13011 | bpr | 539 | /* whether there are too much tries for the exo return yes or no */ |
12213 | bpr | 540 | void calc_getscoremaxexotry(char *p) |
541 | { |
||
542 | _scoreparm(p); |
||
543 | if(*score_class==0 || *score_user==0 || score_sheet==0 || score_exo==0) return; |
||
544 | if(gettrycheck(score_class, score_user, score_sheet, score_exo)==1) |
||
545 | ovlstrcpy(p,"yes"); |
||
546 | else ovlstrcpy(p,"no"); |
||
547 | } |
||
548 | |||
16696 | bpr | 549 | double exam_scoredata[MAX_EXAMS]; |
10 | reyssat | 550 | |
7407 | bpr | 551 | /* get current exam score */ |
10 | reyssat | 552 | void exam_currscore(int esh) |
553 | { |
||
7407 | bpr | 554 | char *p, *bf, pb[MAX_FNAME+1]; |
555 | char *s, *p1, *p2, *e1, *e2; |
||
556 | int i; |
||
16696 | bpr | 557 | for(i=0;i<MAX_EXAMS;i++) exam_scoredata[i]=-1000; |
12814 | bpr | 558 | /* session_prefix is not yet defined here */ |
7407 | bpr | 559 | s=getvar("wims_session"); if(s==NULL || *s==0) return; |
560 | mystrncpy(pb,s,sizeof(pb)); |
||
561 | p=strchr(pb,'_'); if(p!=NULL) *p=0; |
||
562 | bf=readfile(mkfname(NULL,"%s/%s/examscore.%d",session_dir,pb,esh),NULL,WORKFILE_LIMIT); |
||
563 | if(bf==NULL) return; |
||
564 | for(p1=bf;*p1;p1=p2) { |
||
565 | p2=strchr(p1,'\n'); if(*p2) *p2++=0; |
||
566 | else p2=p1+strlen(p1); |
||
567 | p1=find_word_start(find_word_end(find_word_start(p1))); |
||
568 | e1=find_word_end(p1); if(*e1) *e1++=0; |
||
569 | e1=find_word_start(e1); e2=find_word_start(find_word_end(e1)); |
||
570 | *find_word_end(e1)=0; |
||
571 | i=atoi(p1); |
||
16696 | bpr | 572 | if(i>=1 && i<=MAX_EXAMS && |
7407 | bpr | 573 | exam_scoredata[i-1]==-1000 && strcmp(e1,"score")==0) { |
574 | *find_word_end(e2)=0; |
||
575 | exam_scoredata[i-1]=atof(e2); |
||
10 | reyssat | 576 | } |
7407 | bpr | 577 | } |
578 | free(bf); |
||
10 | reyssat | 579 | } |
580 | |||
7407 | bpr | 581 | /* Gather exam score. */ |
10 | reyssat | 582 | void calc_examscore(char *p) |
583 | { |
||
7407 | bpr | 584 | char *p1; |
585 | int i; |
||
9692 | bpr | 586 | char *withoutip; |
7407 | bpr | 587 | |
588 | _scoreparm(p); *p=0; |
||
9692 | bpr | 589 | withoutip=getvar("wims_examscore_withoutip"); |
590 | |||
7407 | bpr | 591 | if(*score_class==0 || *score_user==0) return; |
592 | if(getscoreuser(score_class,score_user)<0) return; |
||
593 | p1=p; |
||
9692 | bpr | 594 | if(withoutip!=NULL && strcmp(withoutip,"yes")==0) { |
595 | for(i=0; i<examcnt && p1-p<MAX_LINELEN-32; i++) { |
||
596 | p1=moneyprint(p1,rscore[examstart+i].best); *p1++=' '; |
||
597 | } |
||
598 | } else { |
||
599 | for(i=0; i<examcnt && p1-p<MAX_LINELEN-32; i++) { |
||
600 | p1=moneyprint(p1,rscore[examstart+i].score); *p1++=' '; |
||
601 | } |
||
7407 | bpr | 602 | } |
603 | *p1++='\n'; |
||
604 | for(i=0; i<examcnt && p1-p<MAX_LINELEN-32; i++) { |
||
605 | p1=moneyprint(p1,rscore[examstart+i].require); *p1++=' '; |
||
606 | p1=moneyprint(p1,floor(rscore[examstart+i].mean/2)); *p1++=' '; |
||
607 | p1=moneyprint(p1,(int) rscore[examstart+i].mean%2); *p1++='\n'; |
||
608 | } |
||
609 | *p1=0; |
||
10 | reyssat | 610 | } |
611 | |||
7407 | bpr | 612 | /* check score dependency. |
8155 | bpr | 613 | * returns 1 if requirements are met. |
614 | */ |
||
10 | reyssat | 615 | int _depcheck(char *ds, struct scoreresult *rs, int ecnt) |
616 | { |
||
7407 | bpr | 617 | char *p1, *p2, *p3, *p4, *pp; |
618 | int perc, t, sum; |
||
619 | double tgot, ttot, tmean; |
||
620 | |||
621 | for(p1=ds; *p1; p1=p3) { |
||
622 | p2=strchr(p1,':'); if(p2==NULL) break; |
||
623 | *p2++=0; p2=find_word_start(p2); |
||
624 | for(p3=p2; myisdigit(*p3); p3++); |
||
625 | if(p3<=p2) break; |
||
15707 | bpr | 626 | if(*p3) *p3++=0; |
627 | perc=atoi(p2); |
||
7407 | bpr | 628 | if(perc<=0 || perc>100) break; |
629 | for(pp=p1; *pp; pp++) if(!myisdigit(*pp)) *pp=' '; |
||
630 | tgot=ttot=tmean=0; sum=0; |
||
631 | for(pp=find_word_start(p1); *pp; pp=find_word_start(p4)) { |
||
632 | p4=find_word_end(pp); if(*p4) *p4++=0; |
||
633 | t=atoi(pp); if(t<=0 || t>ecnt) goto lend; |
||
634 | t--; |
||
635 | ttot+=rs[t].require; tgot+=rs[t].score; tmean+=rs[t].mean; |
||
636 | sum++; |
||
10 | reyssat | 637 | } |
7407 | bpr | 638 | if(ttot<10) continue; |
639 | if(tgot/ttot*sqrt(tmean/(sum*10))*100<perc) { |
||
640 | for(pp=p1;pp<p2-1;pp++) if(!*pp) *pp=','; |
||
641 | *pp=0; setvar("dep_list",p1); |
||
642 | return 0; |
||
643 | } |
||
644 | lend: ; |
||
645 | } |
||
646 | return 1; |
||
10 | reyssat | 647 | } |
648 | |||
649 | int depcheck(char *sh, int exo, char *deps) |
||
650 | { |
||
7407 | bpr | 651 | char buf[MAX_LINELEN+1]; |
652 | char *s, sbuf[64]; |
||
653 | int i, is; |
||
654 | |||
655 | s=getvar("wims_session"); |
||
656 | if(s==NULL || *s==0 || strstr(s,"robot")!=NULL) return 0; |
||
657 | mystrncpy(sbuf,s,sizeof(sbuf)); |
||
658 | s=strchr(sbuf,'_'); if(s) *s=0; |
||
659 | accessfile(buf,"r","../sessions/%s/exodep.%s",sbuf,sh); |
||
660 | if(buf[0]==0) { /* no dep file found */ |
||
661 | is=atoi(sh); if(is<=0 || is>totsheets) return 0; |
||
662 | s=getvar("wims_class"); if(s==NULL || *s==0) return 0; |
||
663 | getscoreuser(s,""); |
||
664 | return _depcheck(deps,rscore+sheetstart[is-1],shexocnt[is-1]); |
||
665 | } |
||
666 | for(i=1,s=strchr(buf,':'); s && i<exo; i++, s=strchr(s+1,':')); |
||
667 | if(s==NULL) return 0; /* bad file or exo number */ |
||
668 | if(myisdigit(*++s)) return 0; else return 1; |
||
10 | reyssat | 669 | } |
670 | |||
671 | int exam_depcheck(char *deps, int exam) |
||
672 | { |
||
16696 | bpr | 673 | static struct scoreresult esc[MAX_EXAMS]; |
7407 | bpr | 674 | int i; |
675 | exam_currscore(exam); |
||
16696 | bpr | 676 | for(i=0;i<MAX_EXAMS;i++) { |
7407 | bpr | 677 | esc[i].require=esc[i].mean=10; |
678 | if(exam_scoredata[i]==-1000) esc[i].score=0; |
||
679 | else esc[i].score=exam_scoredata[i]; |
||
680 | } |
||
16696 | bpr | 681 | return _depcheck(deps,esc,MAX_EXAMS); |
10 | reyssat | 682 | } |
12213 | bpr | 683 | |
12276 | bpr | 684 | /* public sheet gives she=0 */ |
12495 | bpr | 685 | /* return 1 if score is no more taken in account because of exotrymax */ |
12213 | bpr | 686 | int gettrycheck(char *classe, char *user, int she, int exo) { |
687 | char *s; |
||
688 | int sh, ex, i; |
||
13232 | bpr | 689 | if(classe==NULL || *classe==0 || user==NULL || *user==0) return 0; |
12276 | bpr | 690 | if (she<=0) return 0; |
13232 | bpr | 691 | if(strcmp(user,"supervisor")==0) return 0; |
12213 | bpr | 692 | s=getvar("exotrymax"); |
12527 | bpr | 693 | if(s==NULL || *s==0) return 0; |
12213 | bpr | 694 | getscoreuser(classe,user); |
12527 | bpr | 695 | char *p=getvar("wims_scorereg"); |
12213 | bpr | 696 | for(i=0;i<scorecnt;i++) { |
15847 | bpr | 697 | sh=rscore[i].sh+1; |
12213 | bpr | 698 | if (she!=sh) continue; |
15847 | bpr | 699 | ex=rscore[i].exo+1; |
12213 | bpr | 700 | if(exo!=ex) continue; |
12381 | bpr | 701 | if(cmd_type==cmd_new || cmd_type==cmd_renew) |
12527 | bpr | 702 | if(rscore[i].new >= atoi(s)) { |
703 | if(strcmp(p,"suspend")!=0) setvar("wims_scorereg","exotrymax"); |
||
704 | return 1; |
||
705 | } |
||
706 | if(rscore[i].new > atoi(s)){ |
||
707 | if(strcmp(p,"suspend")!=0) setvar("wims_scorereg","exotrymax"); |
||
13015 | bpr | 708 | return 1; |
12527 | bpr | 709 | } |
12508 | bpr | 710 | } |
12213 | bpr | 711 | return 0; |
712 | } |
||
12273 | bpr | 713 | |
714 | /* return seed if the seed should be kept and NULL if not */ |
||
12369 | bpr | 715 | char *getseedscore(char *classe, char *user, int she, int exo) { |
12273 | bpr | 716 | char *s; |
717 | int sh, ex, i; |
||
12276 | bpr | 718 | if (she<=0) return NULL; |
12273 | bpr | 719 | if(strcmp(user,"supervisor")==0) return NULL; |
720 | s=getvar("seedrepeat"); |
||
12990 | bpr | 721 | if(s==NULL || *s==0 || atoi(s)<=0) return NULL; |
12273 | bpr | 722 | getscoreuser(classe,user); |
723 | for(i=0;i<scorecnt;i++) { |
||
15847 | bpr | 724 | sh=rscore[i].sh+1; |
12273 | bpr | 725 | if (she!=sh) continue; |
15847 | bpr | 726 | ex=rscore[i].exo+1; |
12273 | bpr | 727 | if(exo!=ex) continue; |
12432 | bpr | 728 | if(atoi(rscore[i].seedlast)==0) { |
729 | char *seed=getvar("wims_seed"); |
||
730 | return seed; |
||
731 | } |
||
12390 | bpr | 732 | if(rscore[i].seedlastcnt > MAX_SEEDSCORE) return NULL; |
12445 | bpr | 733 | if(atoi(s)>0 && rscore[i].seedlastcnt >= atoi(s) && cmd_type!=cmd_next) return NULL; |
12432 | bpr | 734 | if(rscore[i].seedscorelast < 10) return rscore[i].seedlast; |
12273 | bpr | 735 | }; |
736 | return NULL; |
||
737 | } |