Subversion Repositories wimsdev

Rev

Rev 17885 | 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
 
8185 bpr 18
/* student score management */
10 reyssat 19
 
8185 bpr 20
#include "wimslogd.h"
8253 bpr 21
#define MAX_TRY 60000
10 reyssat 22
double oldfactor=0.85;  /* quality factor, should remain stable. */
23
 
8339 bpr 24
/* User score information of an exercise.
12273 bpr 25
 * size in bytes : 32 +4*MAX_REQUIRE/10 + MAX_SCORESEED*(SEEDSIZE+4)
8339 bpr 26
 * information to change if struct scoredata changes
27
 */
10 reyssat 28
typedef struct scoredata {
15847 bpr 29
  unsigned short int new, allnew, try, hint, seed_scorecnt, seedlastcnt;
12221 bpr 30
  float user, user2, last, best, level, high[MAX_REQUIRE/10];
12273 bpr 31
  struct{
32
    char seed[SEEDSIZE];
33
    float score;
34
  } seed_score[MAX_SCORESEED];
10 reyssat 35
} scoredata;
36
 
12273 bpr 37
struct scoredata uscore[MAX_CLASSEXOS];
38
 
8339 bpr 39
/* size in bytes: 200
40
 * information to change if scoreheader changes
41
 */
10 reyssat 42
struct scoreheader {
12221 bpr 43
  char raf[8][20];
44
  int sheet, exo;
45
  char session[32];
10 reyssat 46
} scoreheader;
47
 
12273 bpr 48
 
10 reyssat 49
#define oldraf scoreheader.raf
50
#define oldsheet scoreheader.sheet
51
#define oldexo scoreheader.exo
52
#define oldsession scoreheader.session
53
 
12224 bpr 54
/* one line of score:
55
  format (see log.c):
56
  exnowstr sess sh exo cc\tip\tse\tallow
57
  allow contains information about noscore
58
  noscore must be at the end to be taken in account
12471 bpr 59
  noscore can be preceded by an explaining word for the moment maxtry
12224 bpr 60
  se is the seed
61
  tabulation is useful in adm/class/userscore/getraw.sh
62
*/
10 reyssat 63
void scoreline(struct classdata *cd, char *l)
64
{
15847 bpr 65
  int i,sheet,exo,num,indnum;
12221 bpr 66
  char *pm[16];
67
  struct scoredata *thiscore;
15847 bpr 68
  struct sheetdata *ts;
12221 bpr 69
  float score;
10 reyssat 70
 
12221 bpr 71
  i=cutwords(l,pm,12); if(i<6) return;
12231 bpr 72
  sheet=atoi(pm[2]); exo=atoi(pm[3]);
16727 guerimand 73
  if(sheet<=0 || sheet>MAX_SHEETS || exo<=0 || exo>MAX_EXOS) return;
15847 bpr 74
  ts=cd->sheets+sheet-1;
75
  num=ts->start+exo-1;
76
  indnum=ts->indstart + exo-1 + ts->exocnt*ts->techval;
12231 bpr 77
  if(num<0) return;
12230 bpr 78
  if(strcmp(pm[i-1],"noscore")==0 || strcmp(pm[i-1],"erased")==0) {
79
    if(strcmp(pm[1],oldsession)!=0)
80
      mystrncpy(oldsession,pm[1],sizeof(oldsession));
12231 bpr 81
    if(strcmp(pm[4],"new")==0 || strcmp(pm[4],"renew")==0) {
82
      thiscore=uscore+num;
83
      thiscore->allnew ++;
12471 bpr 84
      if(i>8) {
12507 bpr 85
        /* copy-paste: seeds are kept even if the last word of the line
12471 bpr 86
          contains noscore
87
         */
12418 bpr 88
        if(thiscore->seed_scorecnt==MAX_SCORESEED) {
89
          int k;
12446 bpr 90
          /* when one reaches the limit one kept at the end only what is necessary to
91
            test if the seed should be changed so MAX_SEEDSCORE
12471 bpr 92
            one wants to keep the first ones (for exotrymax test)
93
           */
12446 bpr 94
          for(k=MAX_SCORESEED-MAX_SEEDSCORE; k<MAX_SCORESEED; ++k)
12418 bpr 95
            thiscore->seed_score[k-1]=thiscore->seed_score[k];
96
          thiscore->seed_scorecnt--;
97
        }
98
        mystrncpy(thiscore->seed_score[thiscore->seed_scorecnt].seed,pm[6],SEEDSIZE);
99
        thiscore->seed_score[thiscore->seed_scorecnt++].score=-2;
100
        thiscore->seedlastcnt=1;
101
        {int k;
102
          for(k=thiscore->seed_scorecnt-1; k>=1 &&
103
              strcmp(thiscore->seed_score[k].seed,thiscore->seed_score[k-1].seed)==0;k--)
104
            thiscore->seedlastcnt++;
105
        }
106
      }
12231 bpr 107
    }
12230 bpr 108
    return;
109
  }
12224 bpr 110
  thiscore=uscore+num;
12471 bpr 111
  /* line with score in word number 5*/
12221 bpr 112
  if(strcmp(pm[4],"score")==0) {
113
    score=atof(pm[5]);
114
    if(!isfinite(score)) score=0;
115
    if(score>10) score=10;
116
    if(score<-10) score=-10;
7149 bpr 117
 
12221 bpr 118
    if(strcmp(pm[1],oldsession)==0 &&   /* measure to prohibit simultaneous scoring. */
7149 bpr 119
        sheet==oldsheet && exo==oldexo &&
7407 bpr 120
        strncmp(pm[0],oldraf[6],13)!=0   /* prohibit scores immediately after rafale */
7149 bpr 121
        ) {
12221 bpr 122
      thiscore->user+=score;
123
      thiscore->user2*=oldfactor;
124
      thiscore->user2+=score;
125
      thiscore->last=score;
126
      if (thiscore->high[0] < score)
127
      {
128
        int k;
129
        thiscore->best += (score - thiscore->high[0]);
15847 bpr 130
        for (k = 1; 10*k < cd->exos[indnum].require && thiscore->high[k] < score; k++)
12221 bpr 131
        thiscore->high[k-1] = thiscore->high[k];
132
        thiscore->high[k-1] = score;
133
        thiscore->level=thiscore->high[0];
134
      }
135
      if(thiscore->try<MAX_TRY) thiscore->try++;
136
      oldsheet=oldexo=0;
12273 bpr 137
      thiscore->seed_score[thiscore->seed_scorecnt-1].score=score;
10 reyssat 138
    }
12221 bpr 139
  }
12471 bpr 140
  /* end of line with score */
12221 bpr 141
  else {
142
    if(strcmp(pm[4],"rafale")==0) { /* rafale punishment */
12231 bpr 143
      if(strncmp(pm[0],oldraf[3],13)==0 && thiscore->new<MAX_TRY)
144
        { thiscore->new++; thiscore->allnew++; }
12221 bpr 145
      memmove(oldraf[1],oldraf[0],sizeof(oldraf[0])*7);
146
      mystrncpy(oldraf[0],pm[0],sizeof(oldraf[0]));
10 reyssat 147
    }
12221 bpr 148
    if(strcmp(pm[4],"resume")!=0 && strcmp(pm[4],"rafale")!=0) {
149
      if(strcmp(pm[4],"hint")==0) thiscore->hint++;
12231 bpr 150
      else if(thiscore->new<MAX_TRY) {
151
        thiscore->new++;
152
        if(thiscore->allnew<MAX_TRY) thiscore->allnew++;
153
      }
12471 bpr 154
      /* what about resume ? */
12273 bpr 155
      if((strcmp(pm[4],"new")==0 || strcmp(pm[4],"renew")==0) && i>6){
156
      /* the first seed is forgotten if there is already MAX_SCORESEED */
157
        if(thiscore->seed_scorecnt==MAX_SCORESEED) {
158
          int k;
159
          for(k=1; k<MAX_SCORESEED; ++k)
160
            thiscore->seed_score[k-1]=thiscore->seed_score[k];
161
          thiscore->seed_scorecnt--;
162
        }
163
        mystrncpy(thiscore->seed_score[thiscore->seed_scorecnt].seed,pm[6],SEEDSIZE);
12295 bpr 164
        thiscore->seed_score[thiscore->seed_scorecnt++].score=-1;
165
        thiscore->seedlastcnt=1;
166
        {int k;
167
          for(k=thiscore->seed_scorecnt-1; k>=1 &&
168
              strcmp(thiscore->seed_score[k].seed,thiscore->seed_score[k-1].seed)==0;k--)
169
            thiscore->seedlastcnt++;
170
        }
171
      }
12221 bpr 172
    }
173
    mystrncpy(oldsession,pm[1],sizeof(oldsession));
174
    oldsheet=sheet; oldexo=exo;
175
  }
10 reyssat 176
}
177
 
178
unsigned int _cuttime(char ends[], char starts[], unsigned int startn)
179
{
12221 bpr 180
  int h1,h2,m1,m2,s2, t;
181
  if(ends[0]==0) return 0;
182
  if(strncmp(ends,starts,14)<0) return 10;
183
  if(strncmp(ends,starts,8)>0) return 0;
184
  h1=atoi(ends+9);   m1=atoi(ends+12);
185
  h2=atoi(starts+9); m2=atoi(starts+12); s2=atoi(starts+15);
186
  t=((h1-h2)*60+(m1-m2))*60-s2;
187
  return startn+t;
10 reyssat 188
}
189
 
8155 bpr 190
/* Gather exam score. */
10 reyssat 191
void examscorecalc(struct classdata *cd, char *uname)
192
{
12221 bpr 193
  struct scoredata *thiscore;
194
  char nbuf[MAX_FNAME+1];
16704 guerimand 195
  char cuttimes[MAX_EXAMS][16];
12221 bpr 196
  char rbuf[MAX_FILELEN+1];
197
  char *wlist[8];
198
  char *p1, *p2;
199
  int i, k, ecnt, num;
16704 guerimand 200
  double ss, sc[MAX_EXAMS], sc2[MAX_EXAMS], scb[MAX_EXAMS], scb2[MAX_EXAMS];
201
  int ind[MAX_EXAMS];
202
  unsigned int tr[MAX_EXAMS], all[MAX_EXAMS], ver[MAX_EXAMS], start[MAX_EXAMS], dure[MAX_EXAMS];
203
  char *ip[MAX_EXAMS], *ses[MAX_EXAMS];
204
  unsigned int start1, endtime[MAX_EXAMS];
12221 bpr 205
  signed int dure1;
10 reyssat 206
 
15847 bpr 207
  ecnt=cd->examcnt;
16081 bpr 208
  if(ecnt<=0) return;
16704 guerimand 209
  if(ecnt>MAX_EXAMS) ecnt=MAX_EXAMS;
12221 bpr 210
  memset(all,0,sizeof(all)), memset(ver,0,sizeof(ver));
211
  for(i=0;i<ecnt;i++) {
15847 bpr 212
    ind[i]=i+cd->exam.indstart;
213
    all[i]=cd->exos[ind[i]].require;
12221 bpr 214
  }
215
  memset(sc,0,sizeof(sc)); memset(sc2,0,sizeof(sc2));
216
  memset(scb,0,sizeof(scb)); memset(scb2,0,sizeof(scb2));
217
  memset(tr,0,sizeof(tr)); memset(cuttimes,0,sizeof(cuttimes));
218
  memset(dure,0,sizeof(dure)); memset(start,0,sizeof(start));
219
  memset(endtime,0,sizeof(endtime));
220
  memset(ip,0,sizeof(ip)); memset(ses,0,sizeof(ses));
221
  snprintf(nbuf,sizeof(nbuf),"score/%s.exam",uname);
222
  readfile(nbuf,rbuf,sizeof(rbuf));
223
  if(rbuf[0]==0) goto end;
224
  for(p1=rbuf; p1!=NULL && *p1; p1=p2) {
225
    p2=strchr(p1,'\n'); if(p2!=NULL) *p2++=0;
226
    i=cutwords(find_word_start(p1),wlist,7);
227
    if(i<6) continue;
228
    i=atoi(wlist[0])-1; if(i<0 || i>=ecnt) continue;
229
    dure1=atoi(wlist[2]); start1=atoi(wlist[3]);
230
    if(strcmp(wlist[1],"--")==0) {     /* session closure */
231
      start[i]=dure[i]=0; ip[i]=ses[i]="";
232
      continue;
10 reyssat 233
    }
12221 bpr 234
    if(strcmp(wlist[1],"00")==0) {
235
      if(sc2[i]<sc[i]) sc2[i]=sc[i];
236
      if(scb2[i]<scb[i]) scb2[i]=scb[i];
237
      ver[i]=1; tr[i]++; start[i]=start1; dure[i]=dure1; sc[i]=0; scb[i]=0;
238
      ip[i]=wlist[4]; ses[i]=wlist[5];
239
      if(tr[i]==1 && wlist[6]!=NULL) {
240
        char *pp1, *pp2, lbuf[CTBUFLEN];
241
        if(cd->ctptr[ind[i]]>=0)
242
          mystrncpy(lbuf,cd->ctbuf+cd->ctptr[ind[i]],sizeof(lbuf));
243
        else lbuf[0]=0;
244
        if(lbuf[0]) {
245
          for(pp1=find_word_start(lbuf); *pp1; pp1=find_word_start(pp2)) {
246
            pp2=find_word_end(pp1); if(pp2-pp1!=14) continue;
247
            if(*pp2) *pp2++=0;
248
            pp1[8]='.'; pp1[11]=':';
249
            if(strcmp(pp1,wlist[6])<0) continue;
250
            memmove(cuttimes[i],pp1,15); break;
7149 bpr 251
          }
12221 bpr 252
        }
253
      }
254
      endtime[i]=_cuttime(cuttimes[i],wlist[6],start1);
255
    }
256
    else if(ver[i]==0) tr[i]++;
257
    if(tr[i]>all[i]) continue;
258
    ss=atof(wlist[1]); if(ss<=0) continue; if(ss>10) ss=10;
12471 bpr 259
    /* checking conditions with ip checking*/
260
    if(ss!=sc[i] && (dure1>=0 || (
261
        start1-start[i]<dure[i]*60 &&
262
        dure[i]>0 && dure[i]<4096 &&
263
        *ses[i]!=0 && *ip[i]!=0 &&
264
        start[i]!=0 && start1>start[i] &&
265
        (endtime[i]==0 || endtime[i]>=start1) &&
266
        strcmp(ip[i],wlist[4])==0 &&
267
        strcmp(ses[i],wlist[5])==0)))
12221 bpr 268
      sc[i]=ss;
12471 bpr 269
    /* checking conditions without ip checking -- will be in structure best */
9692 bpr 270
    if(ss!=scb[i] && (dure1>=0 ||
12471 bpr 271
        (start1-start[i]<dure[i]*60 &&
272
         dure[i]>0 && dure[i]<4096 &&
273
         *ses[i]!=0 && *ip[i]!=0 &&
274
         start[i]!=0 && start1>start[i] &&
275
         (endtime[i]==0 || endtime[i]>=start1) &&
276
         strcmp(ses[i],wlist[5])==0)))
12221 bpr 277
      scb[i]=ss;
278
  }
279
  end:
280
  for(i=0; i<ecnt; i++) {
281
    if(sc2[i]<sc[i]) sc2[i]=sc[i];
282
    if(scb2[i]<scb[i]) scb2[i]=scb[i];
15847 bpr 283
    num=cd->exocnt - cd->examcnt+i;
12221 bpr 284
    if(num<0) continue;
285
    thiscore=uscore+num;
286
    thiscore->user=sc2[i];
287
    thiscore->best=scb2[i];
288
    thiscore->try=tr[i];
289
    if(cuttimes[i][0] && strncmp(cuttimes[i],nowstr,14)<0) k=0; else k=1;
290
    thiscore->hint=k;
291
  }
10 reyssat 292
}
293
 
8155 bpr 294
/* calculate score from raw data, core routine. */
10 reyssat 295
void rawscorecalc(struct classdata *cd, char *uname)
296
{
12221 bpr 297
  char fbuf[MAX_FILELEN+1];
298
  char *p1, *p2;
299
  char namebuf[MAX_FNAME+1];
12471 bpr 300
  /* initialize everything to zero */
12221 bpr 301
  memset(uscore,0,sizeof(uscore[0])*cd->exocnt);
302
  memset(&scoreheader,0,sizeof(scoreheader));
303
  snprintf(namebuf,sizeof(namebuf),"score/%s",uname);
304
  readfile(namebuf,fbuf,sizeof(fbuf));
305
  if(fbuf[0]!=0) {
306
    oldsession[0]=oldsheet=oldexo=0;
307
    for(p1=fbuf; *p1; p1=p2) {
308
      p2=strchr(p1,'\n'); if(p2) *p2++=0; else p2=p1+strlen(p1);
309
      if(myisdigit(*p1)) scoreline(cd,p1);
10 reyssat 310
    }
12221 bpr 311
  }
312
  examscorecalc(cd,uname);
10 reyssat 313
}
314
 
8339 bpr 315
/* size of the file *.bin:
316
 * 200 + (28+4*MAX_REQUIRE/10)*(number_exos_in_sheets + number_exams)
317
 * information to change if struct scoredata or scoreheader change
318
 */
10 reyssat 319
void savescorebin(struct classdata *cd, char *uname)
320
{
12221 bpr 321
  int fd, cnt;
322
  char fname[MAX_FNAME+1];
323
  snprintf(fname,sizeof(fname),"score/%s.bin",uname);
324
  cnt=cd->exocnt;
325
  fd=creat(fname,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
326
  if(fd==-1) return;
327
  (void)write(fd,&scoreheader,sizeof(scoreheader));
328
  (void)write(fd,uscore,sizeof(uscore[0])*cnt);
329
  close(fd);
10 reyssat 330
}
331
 
332
void readscorebin(char *fname,int cnt)
333
{
12221 bpr 334
  int fd;
335
  fd=open(fname,O_RDONLY);
336
  if(fd==-1) return;
337
  (void)read(fd,&scoreheader,sizeof(scoreheader));
338
  (void)read(fd,uscore,sizeof(uscore[0])*cnt);
339
  close(fd);
10 reyssat 340
}
15847 bpr 341
/* copie provisoire  dans wimslogd venant de wims */
342
/*  Get variable definition from a file.
343
 * Result stored in buffer value of length MAX_LINELEN.
344
 */
345
void _getdef(char buf[], char *name, char value[])
346
{
347
  char *p1, *p2, *p3, *p4;
10 reyssat 348
 
15847 bpr 349
  if(*name==0) goto nothing;      /* this would create segfault. */
350
  for(p1=strstr(buf,name); p1!=NULL; p1=strstr(p1+1,name)) {
351
    p2=find_word_start(p1+strlen(name));
352
    if((p1>buf && !isspace(*(p1-1))) || *p2!='=') continue;
353
    p3=p1; while(p3>buf && *(p3-1)!='\n') p3--;
354
    p3=find_word_start(p3);
355
    if(p3<p1 && *p3!='!') continue;
356
    if(p3<p1) {
357
      p3++; p4=find_word_end(p3);
358
      if(find_word_start(p4)!=p1) continue;
359
      if(p4-p3!=3 || (strncmp(p3,"set",3)!=0 &&
360
           strncmp(p3,"let",3)!=0 &&
361
           strncmp(p3,"def",3)!=0)) {
362
        if(p4-p3!=6 || strncmp(p3,"define",6)!=0) continue;
363
      }
364
    }
365
    p2++;p3=strchr(p2,'\n'); if(p3==NULL) p3=p2+strlen(p2);
366
    p2=find_word_start(p2);
367
    if(p2>p3) goto nothing;
368
    /*if(p3-p2>=MAX_LINELEN) user_error("cmd_output_too_long");*/
369
    memmove(value,p2,p3-p2); value[p3-p2]=0;
370
    strip_trailing_spaces(value); return;
371
  }
372
nothing:
373
  value[0]=0;
374
}
375
 
376
void getdef(char *fname, char *name, char value[])
377
{
378
  FILE *f;
379
  char *buf;
380
  int l;
381
 
382
  value[0]=0;
383
  f=fopen(fname,"r"); if(f==NULL) return;
384
  fseek(f,0,SEEK_END); l=ftell(f); fseek(f,0,SEEK_SET);
385
  buf=xmalloc(l+256); l=fread(buf,1,l,f);
386
  fclose(f);
387
  if(l<=0) return; else buf[l]=0;
388
  _getdef(buf,name,value);
389
  free(buf);
390
}
391
/* define number of the technical variable associated to user by sheet */
392
void techvals (struct classdata *cd, char *user)
393
{
394
  char fname[MAX_FNAME+1];
395
  char techname[MAX_FNAME+1], techval[MAX_FNAME+1];
396
  char *p1;
397
  int i, j;
398
 
18421 czzmrn 399
  // snprintf(fname,sizeof(fname),".users/%s",user);
400
  if(cd->sclass[0] != 0 ){
401
    snprintf(fname,sizeof(fname),"%s/%s/%s/.users/%s",cwd,classd,cd->sclass,user);
402
  } else {
403
    snprintf(fname,sizeof(fname),"%s/%s/%s/.users/%s",cwd,classd,cd->name,user);
404
  }
15847 bpr 405
  for (i = 0; i < cd->sheetcnt; ++i){
406
    cd->sheets[i].techval=0;
407
    if (cd->sheets[i].techcnt>1) {
408
      p1 = cd->techs + cd->sheets[i].techoffset;
409
      snprintf(techname,sizeof(techname),"user_techvar_%s", p1);
410
      getdef (fname, techname, techval);
411
      if (techval[0])
412
        for (j = 0; j < cd->sheets[i].techcnt; j++){
413
          p1 += strlen(p1); p1++;
414
          if (!strcmp(techval, p1)) {cd->sheets[i].techval=j; break;}
415
        }
416
      }
417
  }
418
}
419
 
10 reyssat 420
void getscore(struct classdata *cd, char *user)
421
{
12221 bpr 422
  struct stat st[3];
423
  int i, cnt, non[3];
424
  char buf[3][MAX_FNAME+1];
7407 bpr 425
 
12221 bpr 426
  snprintf(buf[0],sizeof(buf[0]),"score/%s",user);
427
  snprintf(buf[1],sizeof(buf[1]),"score/%s.exam",user);
428
  snprintf(buf[2],sizeof(buf[2]),"score/%s.bin",user);
429
  cnt=cd->exocnt; if(cnt<=0) return;
430
  for(i=0;i<3;i++) non[i]=stat(buf[i],st+i);
431
  if(non[0] && non[1]) {
432
    memset(uscore,0,sizeof(uscore[0])*cnt);
433
    memset(&scoreheader,0,sizeof(scoreheader));
434
    return;
435
  }
436
  if(!non[2] &&
437
      st[2].st_size==sizeof(scoreheader)+sizeof(uscore[0])*cnt &&
438
      (non[0] || st[2].st_mtime>=st[0].st_mtime) &&
439
      st[2].st_mtime>=cd->modif) {
440
    readscorebin(buf[2],cnt);
441
    if(!non[1] && st[2].st_mtime<st[1].st_mtime) {
442
      examscorecalc(cd,user);
443
      savescorebin(cd,user);
10 reyssat 444
    }
12221 bpr 445
    return;
446
  }
447
  rawscorecalc(cd,user);
448
  savescorebin(cd,user);
10 reyssat 449
}
450
 
451
void cmd_getscore(char *p)
452
{
12221 bpr 453
  struct classdata *cd;
454
  struct scoreresult tscore[MAX_CLASSEXOS];
455
  char *cut[4];
12471 bpr 456
  int i, j, sheet, exo, snew, stry, thissheet, thisexo;
457
  double score, score2, quality, tt, ts, thisscore, sbest;
458
  float slevel=0;
7638 bpr 459
 
12221 bpr 460
  if(cwdtype!=dir_class) {
461
    sockerror(2,"getscore_no_class"); return;
462
  }
463
  if(*opt_user==0) {
464
    sockerror(2,"getscore_no_user"); return;
465
  }
466
  cd=getclasscache(opt_class);
467
  if(cd==NULL) {
468
    sockerror(2,"getscore_bad_class"); return;
469
  }
470
  if(cutwords(p,cut,3)==3) {
15855 bpr 471
    thissheet=atoi(cut[0])-1; thisexo=atoi(cut[1])-1; thisscore=atof(cut[2]);
12221 bpr 472
    if(!isfinite(thisscore)) thisscore=0;
473
    if(thisscore<-10) thisscore=-10;
474
    if(thisscore>10) thisscore=10;
475
  }
15855 bpr 476
  else {thissheet=thisexo=-1;thisscore=0;}
15847 bpr 477
  techvals(cd,opt_user);
12221 bpr 478
  getscore(cd,opt_user);
15847 bpr 479
  for(i=sheet=0;sheet<=cd->sheetcnt;sheet++){
480
    for(exo=0;exo<cd->sheets[sheet].exocnt;exo++,i++) {
481
      /* j <-> i is the correspondance between the numerotation of
482
        exercises with all versions and with one version */
483
      j=cd->sheets[sheet].indstart+cd->sheets[sheet].techval*cd->sheets[sheet].exocnt+exo;
484
      tscore[i].require=cd->exos[j].require;
17885 bpr 485
      if(cd->exos[j].require==0) {tscore[i].weight=0;}
486
        else {tscore[i].weight=cd->exos[j].weight;}
15847 bpr 487
      tscore[i].active=cd->exos[j].active;
488
      tscore[i].sh=sheet;
489
      tscore[i].exo=exo;
490
      score=uscore[i].user;
491
      stry=uscore[i].try;
492
      score2=uscore[i].user2;
493
      sbest=uscore[i].best;
494
      slevel=uscore[i].level;
495
      /* case of one exo in a sheet */
496
      if(sheet==thissheet && exo==thisexo) {
497
        score+=thisscore;
498
        stry++;
499
        score2*=oldfactor; score2+=thisscore;
500
        /* one compute the new sbest and slevel */
501
        if (uscore[i].high[0] < thisscore) {
502
          sbest += (thisscore - uscore[i].high[0]);
503
          int k;
504
          for (k = 1; 10*k < tscore[i].require && uscore[i].high[k] < thisscore; k++)
505
            uscore[i].high[k-1] = uscore[i].high[k];
506
          uscore[i].high[k-1] = thisscore;
507
          slevel=uscore[i].high[0];
508
        }
12221 bpr 509
      }
15852 bpr 510
      if(sheet==cd->sheetcnt) { /* examens */
15847 bpr 511
        tscore[i].score=score;
512
        tscore[i].mean=stry*2+uscore[i].hint;
513
        tscore[i].try=stry;
514
        tscore[i].best=sbest;
515
        tscore[i].level=slevel;
516
        tscore[i].sh=MAX_SHEETS;
517
        continue;
518
      }
519
      if(score>tscore[i].require) score=tscore[i].require;
520
      if(stry>0) {
15852 bpr 521
      snew=uscore[i].new; if(uscore[i].hint>0) snew++;
15847 bpr 522
        /* here we give up to 1 time unsuccessful tries.
523
         * Together with a premium of 5 uncounted tries.
524
         */
525
        if(snew<stry*2+5) tt=1;
526
        else tt=(double) (snew-4)/(2*stry); /* tt>=1 */
527
        ts=(1-pow(oldfactor,stry))/(1-oldfactor);
528
        quality=score2/(ts*tt);
529
      }
530
      else {
531
        score=quality=stry=sbest=slevel=0;
532
      }
12221 bpr 533
      tscore[i].score=score;
15847 bpr 534
      tscore[i].mean=quality;
12221 bpr 535
      tscore[i].try=stry;
536
      tscore[i].best=sbest;
537
      tscore[i].level=slevel;
15847 bpr 538
      tscore[i].last=uscore[i].last;
539
      tscore[i].new=uscore[i].allnew;
540
      mystrncpy(tscore[i].seedlast,
541
        uscore[i].seed_score[uscore[i].seed_scorecnt-1].seed,SEEDSIZE);
542
      tscore[i].seedscorelast=uscore[i].seed_score[uscore[i].seed_scorecnt-1].score;
543
      p=tscore[i].seedscores;
544
      *p++ = '[';
545
      for(j=0;j<uscore[i].seed_scorecnt;j++){
546
        if (j) *p++=';';
547
        mystrncpy(p,uscore[i].seed_score[j].seed,SEEDSIZE);
548
        p+=strlen(p); *p++=',';
549
        p=moneyprint(p,uscore[i].seed_score[j].score);
550
      }
551
      *p++ = ']'; *p=0;
552
      tscore[i].seedlastcnt=uscore[i].seedlastcnt;
10 reyssat 553
    }
12221 bpr 554
  }
555
  answerlen=cd->exocnt*sizeof(tscore[0]);
556
  memmove(textbuf+3,tscore,answerlen);
557
  answerlen+=3;
10 reyssat 558
}
559
 
560
void cmd_scorelog(char *p)
561
{
12221 bpr 562
  struct classdata *cd;
563
  char buf[MAX_LINELEN+1];
7407 bpr 564
 
12221 bpr 565
  if(cwdtype!=dir_class) {
566
    sockerror(2,"scorelog_no_class"); return;
567
  }
568
  if(*opt_user==0) {
569
    sockerror(2,"scorelog_no_user"); return;
570
  }
571
  cd=getclasscache(opt_class);
572
  if(cd==NULL) {
573
    sockerror(2,"scorelog_bad_class"); return;
574
  }
575
  getscore(cd,opt_user);
576
  p=find_word_start(p); strip_trailing_spaces(p);
577
  snprintf(buf,sizeof(buf),"%s\n",p);
578
  wlogdaccessfile(buf,"a","score/%s",opt_user);
579
  if(myisdigit(*p)) scoreline(cd,p);
580
  savescorebin(cd,opt_user);
10 reyssat 581
}