Rev 18153 | 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; |
18414 | bpr | 372 | char *classp, *classp2, *scp; |
18087 | bpr | 373 | char *p1,buf1[MAX_LINELEN],buf2[MAX_LINELEN]; |
374 | char buf3[MAX_LINELEN],buf4[MAX_LINELEN]; |
||
375 | if(isexam || score_isexam) {st="exam"; lnb=8;} else {st="sheet";lnb=9;}; |
||
7407 | bpr | 376 | mkfname(namebuf,"%s/%s/%ss/.%ss",class_base,classe,st,st); |
377 | direct_datafile=1;datafile_fnd_record(namebuf,sheet,buf);direct_datafile=0; |
||
378 | p=find_word_start(buf); if(*p==0) return -1; |
||
379 | i=*p-'0'; if(i>5 || i<0) i=-1; |
||
380 | if((isexam || score_isexam) && i==0) { |
||
381 | p=getvar("wims_user"); if(p!=NULL && strcmp(p,"supervisor")==0) i=1; |
||
382 | } |
||
18081 | bpr | 383 | res=i; |
384 | if (res == 0 || res > 2) |
||
385 | goto ret; |
||
386 | if (strcmp(score_user,"supervisor")==0 || score_user[0]==0) |
||
387 | goto ret; |
||
18087 | bpr | 388 | fnd_line(buf,lnb,buf1); |
389 | rows2lines(buf1); |
||
18414 | bpr | 390 | classp=getvar("wims_class"); scp=getvar("wims_superclass"); |
391 | if(scp!=NULL && *scp!=0) classp2=scp; else classp2=classp; |
||
392 | mkfname(namebuf,"%s/%s/.users/%s",class_base,classp2,score_user); |
||
18081 | bpr | 393 | for(i=1;;++i){ |
18087 | bpr | 394 | fnd_line(buf1,i,buf); |
18081 | bpr | 395 | if(*buf==0) break; |
396 | for (j=1;;++j){ |
||
18087 | bpr | 397 | fnd_item(buf,j,buf2); |
398 | if (buf2[0]==0) {res = 3; goto ret;} |
||
399 | p1=strchr(buf2,'='); |
||
18081 | bpr | 400 | if(p1==NULL) break; |
401 | *p1=0; |
||
18087 | bpr | 402 | snprintf(buf3,sizeof(buf3),"%s_%s","user_techvar",buf2); |
403 | getdef(namebuf,buf3,buf4); |
||
404 | if(strcmp(buf4,p1+1)) break; |
||
18081 | bpr | 405 | } |
406 | } |
||
407 | ret: |
||
408 | return res; |
||
10 | reyssat | 409 | } |
410 | |||
13011 | bpr | 411 | /* return 1 if a word of bf2 is a substring of host |
412 | and if time restrictions are verified for wims_user |
||
8155 | bpr | 413 | * Content of bf2 is destroyed. |
414 | */ |
||
10303 | guerimand | 415 | int _subword(char bf2[],char *ftbuf) |
10 | reyssat | 416 | { |
7407 | bpr | 417 | char *p1, *p2; |
418 | for(p1=strchr(bf2,'\\'); p1!=NULL; p1=strchr(p1+1,'\\')) { |
||
419 | char buf[MAX_LINELEN+1], buf2[MAX_LINELEN+1], fbuf[MAX_FNAME+1]; |
||
420 | char *classp, *classp2, *userp, *scp; |
||
421 | classp=getvar("wims_class"); userp=getvar("wims_user"); |
||
422 | if(classp==NULL || userp==NULL || *classp==0 || *userp==0) break; |
||
423 | scp=getvar("wims_superclass"); |
||
424 | if(scp!=NULL && *scp!=0) classp2=scp; else classp2=classp; |
||
425 | if(p1>bf2 && !isspace(*(p1-1))) continue; |
||
426 | if(!isalnum(*(p1+1))) continue; |
||
427 | p2=find_word_end(p1); if(p2>=p1+MAX_NAMELEN) continue; |
||
428 | memmove(buf2, p1+1, p2-p1-1); buf2[p2-p1-1]=0; |
||
18081 | bpr | 429 | /* get value of technical variable for user */ |
10303 | guerimand | 430 | snprintf(buf,sizeof(buf),"user_techvar_%s",buf2); |
7407 | bpr | 431 | if(strcmp(userp,"supervisor")==0) |
432 | mkfname(fbuf,"%s/%s/supervisor",class_base,classp); |
||
433 | else |
||
434 | mkfname(fbuf,"%s/%s/.users/%s",class_base,classp2,userp); |
||
10303 | guerimand | 435 | getdef(fbuf,buf,buf2); |
18081 | bpr | 436 | /* end value for the user */ |
10365 | bpr | 437 | if(buf2[0]==0) ovlstrcpy(buf2,"EMPTY"); /* in case of no value defined for the user*/ |
10303 | guerimand | 438 | /* get time restriction for this value */ |
439 | snprintf(buf,sizeof(buf),"techvar_%s",buf2); |
||
13011 | bpr | 440 | /* mkfname(fbuf,"%s/%s/.E%s",class_base,classp,sheet); |
441 | * read time restriction corresponding to the value of |
||
442 | * technical variable in the file of the sheet or exam |
||
443 | */ |
||
10379 | bpr | 444 | getdef(ftbuf,buf,buf2); |
18081 | bpr | 445 | /* value for techvar */ |
10303 | guerimand | 446 | if(buf2[0]==0) ovlstrcpy(buf2,"none"); |
447 | /*string_modify(bf2,p1,p2,buf2);*/ |
||
448 | bf2=buf2; |
||
7407 | bpr | 449 | p1+=strlen(buf2); |
450 | } |
||
451 | if((isexam || score_isexam) && bf2[0]=='#') return 1; |
||
452 | if(wordchr(bf2,"none")!=NULL) return 0; |
||
453 | if(wordchr(bf2,"all")!=NULL) return 1; |
||
454 | p1=find_word_start(bf2); if(*p1==0) return 1; |
||
13011 | bpr | 455 | /* check host and time */ |
7407 | bpr | 456 | return checkhostt(p1); |
10 | reyssat | 457 | } |
458 | |||
13011 | bpr | 459 | /* Returns 1 if score registration is open for the user |
460 | * in variable wims_user, 0 otherwise. |
||
461 | */ |
||
10 | reyssat | 462 | int _getscorestatus(char *classe, int sheet) |
463 | { |
||
7407 | bpr | 464 | char nbuf[MAX_LINELEN+1], gbuf[MAX_LINELEN+1]; |
10303 | guerimand | 465 | char ftbuf[MAX_FNAME+1]=""; |
7407 | bpr | 466 | char *es; |
10 | reyssat | 467 | |
7407 | bpr | 468 | if(classe==NULL || *classe==0 || sheet<=0) return 1; |
469 | if(getsheetstatus(classe,sheet)!=1) return 0; |
||
470 | if(*remote_addr==0) return 0; |
||
471 | if(isexam || score_isexam) { /* exam simulation */ |
||
472 | accessfile(nbuf,"r","%s/%s/.E%d",class_base,classe,sheet); |
||
473 | if(nbuf[0]=='#') return 1; |
||
474 | } |
||
12814 | bpr | 475 | /* Global restriction data */ |
7407 | bpr | 476 | accessfile(nbuf,"r","%s/%s/.security",class_base,classe); |
477 | if(nbuf[0]) { |
||
478 | _getdef(nbuf,"allow",gbuf); |
||
10303 | guerimand | 479 | if(*find_word_start(gbuf)!=0 && _subword(gbuf,ftbuf)==0) |
7407 | bpr | 480 | return 0; |
481 | _getdef(nbuf,"except",gbuf); |
||
10303 | guerimand | 482 | if(*find_word_start(gbuf)!=0 && _subword(gbuf,ftbuf)==1) |
7407 | bpr | 483 | return 0; |
484 | } |
||
13011 | bpr | 485 | /* Sheet restriction data; take in account the technical variables */ |
7407 | bpr | 486 | if(isexam || score_isexam) es="E"; else es=""; |
487 | accessfile(nbuf,"r","%s/%s/.%s%d",class_base,classe,es,sheet); |
||
488 | if(*find_word_start(nbuf)==0) return 1; |
||
12814 | bpr | 489 | /* preparing score restriction file name :*/ |
10303 | guerimand | 490 | mkfname(ftbuf,"%s/%s/.%s%d",class_base,classe,es,sheet); |
491 | return _subword(nbuf,ftbuf); |
||
10 | reyssat | 492 | } |
493 | |||
13011 | bpr | 494 | /* Returns 1 if score registration is open for wims_user, 0 otherwise.*/ |
10 | reyssat | 495 | int getscorestatus(char *classe, int sheet) |
496 | { |
||
7407 | bpr | 497 | if(score_status<0 || score_statussheet!=sheet |
498 | || score_statusisexam!=isexam) { |
||
499 | score_statussheet=sheet; score_statusisexam=isexam; |
||
500 | score_status=_getscorestatus(classe,sheet); score_isexam=0; |
||
17457 | guerimand | 501 | if(score_status!=0 && (cmd_type==cmd_new || cmd_type==cmd_renew |
7646 | bpr | 502 | || isexam)) { |
7407 | bpr | 503 | char *p; |
504 | p=getvar("wims_scorereg"); |
||
505 | if(p==NULL || strcmp(p,"suspend")!=0) |
||
7646 | bpr | 506 | setvar("wims_scoring","pending"); |
7407 | bpr | 507 | else setvar("wims_scoring",""); |
10 | reyssat | 508 | } |
7407 | bpr | 509 | } |
510 | if(isexam && score_status==0) { |
||
511 | char *p; |
||
13557 | obado | 512 | p=getvar("wims_user"); |
513 | if(p==NULL || strcmp(p,"supervisor")!=0) |
||
514 | user_error("exam_closed"); |
||
7407 | bpr | 515 | } |
516 | return score_status; |
||
10 | reyssat | 517 | } |
518 | |||
7407 | bpr | 519 | /* Whether score registering is open */ |
10 | reyssat | 520 | void calc_getscorestatus(char *p) |
521 | { |
||
7407 | bpr | 522 | _scoreparm(p); |
523 | if(*score_class==0 || score_sheet==0 || *score_user==0) { |
||
524 | *p=0; return; |
||
525 | } |
||
526 | if(getscorestatus(score_class, score_sheet)) |
||
527 | ovlstrcpy(p,"yes"); |
||
528 | else ovlstrcpy(p,"no"); |
||
10 | reyssat | 529 | } |
530 | |||
18056 | bpr | 531 | /* get status of a sheet in a class: can be 0, 1, 2 or 3 |
18091 | bpr | 532 | (in preparation, active, expired or hidden) */ |
18056 | bpr | 533 | void calc_getsheetstatus(char *p) |
534 | { |
||
535 | _scoreparm(p); |
||
18087 | bpr | 536 | if(*score_class==0 || (score_sheet==0 && score_isexam==0)) { |
18056 | bpr | 537 | *p=0; return; |
538 | } |
||
18153 | bpr | 539 | snprintf(p,20,"%d",getsheetstatus(score_class, score_sheet?score_sheet:score_exam)); |
18056 | bpr | 540 | } |
541 | |||
13011 | bpr | 542 | /* whether there are too much tries for the exo return yes or no */ |
12213 | bpr | 543 | void calc_getscoremaxexotry(char *p) |
544 | { |
||
545 | _scoreparm(p); |
||
546 | if(*score_class==0 || *score_user==0 || score_sheet==0 || score_exo==0) return; |
||
547 | if(gettrycheck(score_class, score_user, score_sheet, score_exo)==1) |
||
548 | ovlstrcpy(p,"yes"); |
||
549 | else ovlstrcpy(p,"no"); |
||
550 | } |
||
551 | |||
16696 | bpr | 552 | double exam_scoredata[MAX_EXAMS]; |
10 | reyssat | 553 | |
7407 | bpr | 554 | /* get current exam score */ |
10 | reyssat | 555 | void exam_currscore(int esh) |
556 | { |
||
7407 | bpr | 557 | char *p, *bf, pb[MAX_FNAME+1]; |
558 | char *s, *p1, *p2, *e1, *e2; |
||
559 | int i; |
||
16696 | bpr | 560 | for(i=0;i<MAX_EXAMS;i++) exam_scoredata[i]=-1000; |
12814 | bpr | 561 | /* session_prefix is not yet defined here */ |
7407 | bpr | 562 | s=getvar("wims_session"); if(s==NULL || *s==0) return; |
563 | mystrncpy(pb,s,sizeof(pb)); |
||
564 | p=strchr(pb,'_'); if(p!=NULL) *p=0; |
||
565 | bf=readfile(mkfname(NULL,"%s/%s/examscore.%d",session_dir,pb,esh),NULL,WORKFILE_LIMIT); |
||
566 | if(bf==NULL) return; |
||
567 | for(p1=bf;*p1;p1=p2) { |
||
568 | p2=strchr(p1,'\n'); if(*p2) *p2++=0; |
||
569 | else p2=p1+strlen(p1); |
||
570 | p1=find_word_start(find_word_end(find_word_start(p1))); |
||
571 | e1=find_word_end(p1); if(*e1) *e1++=0; |
||
572 | e1=find_word_start(e1); e2=find_word_start(find_word_end(e1)); |
||
573 | *find_word_end(e1)=0; |
||
574 | i=atoi(p1); |
||
16696 | bpr | 575 | if(i>=1 && i<=MAX_EXAMS && |
7407 | bpr | 576 | exam_scoredata[i-1]==-1000 && strcmp(e1,"score")==0) { |
577 | *find_word_end(e2)=0; |
||
578 | exam_scoredata[i-1]=atof(e2); |
||
10 | reyssat | 579 | } |
7407 | bpr | 580 | } |
581 | free(bf); |
||
10 | reyssat | 582 | } |
583 | |||
7407 | bpr | 584 | /* Gather exam score. */ |
10 | reyssat | 585 | void calc_examscore(char *p) |
586 | { |
||
7407 | bpr | 587 | char *p1; |
588 | int i; |
||
9692 | bpr | 589 | char *withoutip; |
7407 | bpr | 590 | |
591 | _scoreparm(p); *p=0; |
||
9692 | bpr | 592 | withoutip=getvar("wims_examscore_withoutip"); |
593 | |||
7407 | bpr | 594 | if(*score_class==0 || *score_user==0) return; |
595 | if(getscoreuser(score_class,score_user)<0) return; |
||
596 | p1=p; |
||
9692 | bpr | 597 | if(withoutip!=NULL && strcmp(withoutip,"yes")==0) { |
598 | for(i=0; i<examcnt && p1-p<MAX_LINELEN-32; i++) { |
||
599 | p1=moneyprint(p1,rscore[examstart+i].best); *p1++=' '; |
||
600 | } |
||
601 | } else { |
||
602 | for(i=0; i<examcnt && p1-p<MAX_LINELEN-32; i++) { |
||
603 | p1=moneyprint(p1,rscore[examstart+i].score); *p1++=' '; |
||
604 | } |
||
7407 | bpr | 605 | } |
606 | *p1++='\n'; |
||
607 | for(i=0; i<examcnt && p1-p<MAX_LINELEN-32; i++) { |
||
608 | p1=moneyprint(p1,rscore[examstart+i].require); *p1++=' '; |
||
609 | p1=moneyprint(p1,floor(rscore[examstart+i].mean/2)); *p1++=' '; |
||
610 | p1=moneyprint(p1,(int) rscore[examstart+i].mean%2); *p1++='\n'; |
||
611 | } |
||
612 | *p1=0; |
||
10 | reyssat | 613 | } |
614 | |||
7407 | bpr | 615 | /* check score dependency. |
8155 | bpr | 616 | * returns 1 if requirements are met. |
617 | */ |
||
10 | reyssat | 618 | int _depcheck(char *ds, struct scoreresult *rs, int ecnt) |
619 | { |
||
7407 | bpr | 620 | char *p1, *p2, *p3, *p4, *pp; |
621 | int perc, t, sum; |
||
622 | double tgot, ttot, tmean; |
||
623 | |||
624 | for(p1=ds; *p1; p1=p3) { |
||
625 | p2=strchr(p1,':'); if(p2==NULL) break; |
||
626 | *p2++=0; p2=find_word_start(p2); |
||
627 | for(p3=p2; myisdigit(*p3); p3++); |
||
628 | if(p3<=p2) break; |
||
15707 | bpr | 629 | if(*p3) *p3++=0; |
630 | perc=atoi(p2); |
||
7407 | bpr | 631 | if(perc<=0 || perc>100) break; |
632 | for(pp=p1; *pp; pp++) if(!myisdigit(*pp)) *pp=' '; |
||
633 | tgot=ttot=tmean=0; sum=0; |
||
634 | for(pp=find_word_start(p1); *pp; pp=find_word_start(p4)) { |
||
635 | p4=find_word_end(pp); if(*p4) *p4++=0; |
||
636 | t=atoi(pp); if(t<=0 || t>ecnt) goto lend; |
||
637 | t--; |
||
638 | ttot+=rs[t].require; tgot+=rs[t].score; tmean+=rs[t].mean; |
||
639 | sum++; |
||
10 | reyssat | 640 | } |
7407 | bpr | 641 | if(ttot<10) continue; |
642 | if(tgot/ttot*sqrt(tmean/(sum*10))*100<perc) { |
||
643 | for(pp=p1;pp<p2-1;pp++) if(!*pp) *pp=','; |
||
644 | *pp=0; setvar("dep_list",p1); |
||
645 | return 0; |
||
646 | } |
||
647 | lend: ; |
||
648 | } |
||
649 | return 1; |
||
10 | reyssat | 650 | } |
651 | |||
652 | int depcheck(char *sh, int exo, char *deps) |
||
653 | { |
||
7407 | bpr | 654 | char buf[MAX_LINELEN+1]; |
655 | char *s, sbuf[64]; |
||
656 | int i, is; |
||
657 | |||
658 | s=getvar("wims_session"); |
||
659 | if(s==NULL || *s==0 || strstr(s,"robot")!=NULL) return 0; |
||
660 | mystrncpy(sbuf,s,sizeof(sbuf)); |
||
661 | s=strchr(sbuf,'_'); if(s) *s=0; |
||
662 | accessfile(buf,"r","../sessions/%s/exodep.%s",sbuf,sh); |
||
663 | if(buf[0]==0) { /* no dep file found */ |
||
664 | is=atoi(sh); if(is<=0 || is>totsheets) return 0; |
||
665 | s=getvar("wims_class"); if(s==NULL || *s==0) return 0; |
||
666 | getscoreuser(s,""); |
||
667 | return _depcheck(deps,rscore+sheetstart[is-1],shexocnt[is-1]); |
||
668 | } |
||
669 | for(i=1,s=strchr(buf,':'); s && i<exo; i++, s=strchr(s+1,':')); |
||
670 | if(s==NULL) return 0; /* bad file or exo number */ |
||
671 | if(myisdigit(*++s)) return 0; else return 1; |
||
10 | reyssat | 672 | } |
673 | |||
674 | int exam_depcheck(char *deps, int exam) |
||
675 | { |
||
16696 | bpr | 676 | static struct scoreresult esc[MAX_EXAMS]; |
7407 | bpr | 677 | int i; |
678 | exam_currscore(exam); |
||
16696 | bpr | 679 | for(i=0;i<MAX_EXAMS;i++) { |
7407 | bpr | 680 | esc[i].require=esc[i].mean=10; |
681 | if(exam_scoredata[i]==-1000) esc[i].score=0; |
||
682 | else esc[i].score=exam_scoredata[i]; |
||
683 | } |
||
16696 | bpr | 684 | return _depcheck(deps,esc,MAX_EXAMS); |
10 | reyssat | 685 | } |
12213 | bpr | 686 | |
12276 | bpr | 687 | /* public sheet gives she=0 */ |
12495 | bpr | 688 | /* return 1 if score is no more taken in account because of exotrymax */ |
12213 | bpr | 689 | int gettrycheck(char *classe, char *user, int she, int exo) { |
690 | char *s; |
||
691 | int sh, ex, i; |
||
13232 | bpr | 692 | if(classe==NULL || *classe==0 || user==NULL || *user==0) return 0; |
12276 | bpr | 693 | if (she<=0) return 0; |
13232 | bpr | 694 | if(strcmp(user,"supervisor")==0) return 0; |
12213 | bpr | 695 | s=getvar("exotrymax"); |
12527 | bpr | 696 | if(s==NULL || *s==0) return 0; |
12213 | bpr | 697 | getscoreuser(classe,user); |
12527 | bpr | 698 | char *p=getvar("wims_scorereg"); |
12213 | bpr | 699 | for(i=0;i<scorecnt;i++) { |
15847 | bpr | 700 | sh=rscore[i].sh+1; |
12213 | bpr | 701 | if (she!=sh) continue; |
15847 | bpr | 702 | ex=rscore[i].exo+1; |
12213 | bpr | 703 | if(exo!=ex) continue; |
12381 | bpr | 704 | if(cmd_type==cmd_new || cmd_type==cmd_renew) |
12527 | bpr | 705 | if(rscore[i].new >= atoi(s)) { |
706 | if(strcmp(p,"suspend")!=0) setvar("wims_scorereg","exotrymax"); |
||
707 | return 1; |
||
708 | } |
||
709 | if(rscore[i].new > atoi(s)){ |
||
710 | if(strcmp(p,"suspend")!=0) setvar("wims_scorereg","exotrymax"); |
||
13015 | bpr | 711 | return 1; |
12527 | bpr | 712 | } |
12508 | bpr | 713 | } |
12213 | bpr | 714 | return 0; |
715 | } |
||
12273 | bpr | 716 | |
717 | /* return seed if the seed should be kept and NULL if not */ |
||
12369 | bpr | 718 | char *getseedscore(char *classe, char *user, int she, int exo) { |
12273 | bpr | 719 | char *s; |
720 | int sh, ex, i; |
||
12276 | bpr | 721 | if (she<=0) return NULL; |
12273 | bpr | 722 | if(strcmp(user,"supervisor")==0) return NULL; |
723 | s=getvar("seedrepeat"); |
||
12990 | bpr | 724 | if(s==NULL || *s==0 || atoi(s)<=0) return NULL; |
12273 | bpr | 725 | getscoreuser(classe,user); |
726 | for(i=0;i<scorecnt;i++) { |
||
15847 | bpr | 727 | sh=rscore[i].sh+1; |
12273 | bpr | 728 | if (she!=sh) continue; |
15847 | bpr | 729 | ex=rscore[i].exo+1; |
12273 | bpr | 730 | if(exo!=ex) continue; |
12432 | bpr | 731 | if(atoi(rscore[i].seedlast)==0) { |
732 | char *seed=getvar("wims_seed"); |
||
733 | return seed; |
||
734 | } |
||
12390 | bpr | 735 | if(rscore[i].seedlastcnt > MAX_SEEDSCORE) return NULL; |
12445 | bpr | 736 | if(atoi(s)>0 && rscore[i].seedlastcnt >= atoi(s) && cmd_type!=cmd_next) return NULL; |
12432 | bpr | 737 | if(rscore[i].seedscorelast < 10) return rscore[i].seedlast; |
12273 | bpr | 738 | }; |
739 | return NULL; |
||
740 | } |