Back to index

wims  3.65+svn20090927
exostat.c
Go to the documentation of this file.
00001 /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
00002  *
00003  *  This program is free software; you can redistribute it and/or modify
00004  *  it under the terms of the GNU General Public License as published by
00005  *  the Free Software Foundation; either version 2 of the License, or
00006  *  (at your option) any later version.
00007  *
00008  *  This program is distributed in the hope that it will be useful,
00009  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  *  GNU General Public License for more details.
00012  *
00013  *  You should have received a copy of the GNU General Public License
00014  *  along with this program; if not, write to the Free Software
00015  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00016  */
00017 
00018        /* This is an internal program,
00019         * used to show statistics of frequentation, module by module. */
00020 
00021 #include "../Lib/libwims.h"
00022 
00023 #define MAX_EXO             64
00024 #define MAX_SHEET    64
00025 #define MAX_EXAM     32
00026 #define MAX_SCORE    512*1024
00027 
00028 typedef struct {
00029     short int dure,score;
00030     long int next;
00031 } scoredata;
00032 scoredata scores[MAX_SCORE];
00033 int sccnt=0;
00034 
00035 typedef struct {
00036     int newcnt,scorecnt,lasttime,firstscore,lastscore;
00037     char lastnew[12];
00038 } exodata;
00039 exodata shdata[MAX_SHEET*MAX_EXO],examdata[MAX_EXAM*MAX_EXO];
00040 
00041 /* cid: combined index of difficulty */
00042 double scsum, scavg, scdeviat, scmin, scmax, cid;
00043 double dursum, duravg, durdeviat, durmin, durmax;
00044 
00045 int filecnt=0, fcind;
00046 char *dirbase, types[256];
00047 
00048 int str2time(char *p)
00049 {
00050     int sec,min,hr;
00051     sec=atoi(p+15); p[14]=0;
00052     min=atoi(p+12); p[11]=0;
00053     hr=atoi(p+9);
00054     if(sec<0 || min<0 || hr<0 || sec>59 || min>59 || hr>23) return -1;
00055     return hr*3600+min*60+sec;
00056 }
00057 
00058 void oneline(char *p)
00059 {
00060     int i, sh, ex, t;
00061     char *data[64];
00062     exodata *tab;
00063     char *pp, *pe;
00064 
00065     for(i=0, pp=find_word_start(p); i<8 && *pp; pp=find_word_start(pe),i++) {
00066        pe=find_word_end(pp); if(*pe) *pe++=0;
00067        data[i]=pp;
00068     }
00069     if(i<6) return;
00070     sh=atoi(data[2]); ex=atoi(data[3]);
00071     if(sh<=0 || ex<=0 || ex>MAX_EXO || strlen(data[1])>10) return;
00072     if(data[0][0]=='E') {
00073        tab=examdata; data[0]++; if(sh>MAX_EXAM) return;
00074     }
00075     else {
00076        tab=shdata; if(sh>MAX_SHEET) return;
00077     }
00078     tab+=(sh-1)*MAX_EXO+(ex-1);
00079     t=str2time(data[0]); if(t==-1) return;
00080     if(strstr(data[4],"new")!=NULL) {
00081        snprintf(tab->lastnew,12,"%s",data[1]);
00082        tab->newcnt++; tab->lasttime=t;
00083        fcind++;
00084        return;
00085     }
00086     if(strcmp(data[4],"score")==0) {
00087        if(strcmp(tab->lastnew,data[1])!=0) return;
00088        if(sccnt>=MAX_SCORE) return;
00089        if(tab->lasttime==-1) return;
00090        t-=tab->lasttime; tab->lasttime=-1; if(t<0) t+=24*3600;
00091        if(t<0) t=0; if(t>5*3600) t=5*3600;
00092        scores[sccnt].dure=t; scores[sccnt].next=-1;
00093        scores[sccnt].score=(double) atof(data[5])*100+0.5;
00094        if(tab->scorecnt>0) scores[tab->lastscore].next=sccnt;
00095        else tab->firstscore=sccnt;
00096        tab->lastscore=sccnt; sccnt++; tab->scorecnt++;
00097     }
00098 }
00099 
00100 void onefile(char *fname)
00101 {
00102     FILE *f;
00103     char *buf, *pp, *pe;
00104     long int l;
00105     f=fopen(fname,"r"); if(f==NULL) return;
00106     fseek(f,0,SEEK_END); l=ftell(f); fseek(f,0,SEEK_SET);
00107     if(l<=0) {fclose(f); return;}
00108     buf=xmalloc(l+16); fread(buf,1,l,f); fclose(f); buf[l]=0;
00109     fcind=0;
00110     for(pp=buf; pp; pp=pe) {
00111        pe=strchr(pp,'\n'); if(pe!=NULL) *pe++=0;
00112        oneline(pp);
00113     }
00114     free(buf);
00115     if(fcind>0) filecnt++;
00116 }
00117 
00118 void onedir(char *dirname)
00119 {
00120     char buf[MAX_LINELEN+1], buf2[MAX_LINELEN+1];
00121     DIR *dir;
00122     struct dirent *ff;
00123     char *t1, *t2;
00124     
00125     for(t1=find_word_start(types); *t1; t1=find_word_start(t2)) {
00126        t2=find_word_end(t1); if(*t2) *t2++=0;
00127        snprintf(buf,sizeof(buf),"%s/%s/%s",dirbase,dirname,t1);
00128        dir=opendir(buf); if(dir==NULL) return;
00129        while((ff=readdir(dir))!=NULL) {
00130            if(!isalnum(ff->d_name[0]) ||
00131               strcmp(ff->d_name,"supervisor")==0) continue;
00132            snprintf(buf2,sizeof(buf2),"%s/%s",buf,ff->d_name);
00133            onefile(buf2);
00134        }
00135        closedir(dir);
00136     }
00137 }
00138 
00139 void stati(exodata *dat)
00140 {
00141     int i,j;
00142     double s,d;
00143     
00144     scsum=scavg=scdeviat=dursum=duravg=durdeviat=cid=0;
00145     scmin=10; scmax=0; durmin=24*3600; durmax=0;
00146     for(i=0,j=dat->firstscore; i<dat->scorecnt; i++) {
00147        s=(double) scores[j].score/100; d=(double) scores[j].dure/60;
00148        scsum+=s; dursum+=d;
00149        if(scmin>s) scmin=s; if(scmax<s) scmax=s;
00150        if(durmin>d) durmin=d; if(durmax<d) durmax=d;
00151        j=scores[j].next;
00152     }
00153     if(i<=0) {scmin=durmin=0; return;}
00154     scavg=scsum/i; duravg=dursum/i;
00155     if(scsum>1) cid=min(4*sqrt(dursum*dat->newcnt)/scsum,99);
00156     else cid=0;
00157     if(i>=2) {
00158        for(i=0,j=dat->firstscore; i<dat->scorecnt; i++) {
00159            s=(double) scores[j].score/100; d=(double) scores[j].dure/60;
00160            scdeviat+=(s-scavg)*(s-scavg); durdeviat+=(d-duravg)*(d-duravg);
00161            j=scores[j].next;
00162        }
00163        scdeviat=sqrt(scdeviat/i); durdeviat=sqrt(durdeviat/i);
00164     }
00165 }
00166 
00167        /* Output line format:
00168         * type sh exo newcnt scorecnt scsum dursum scavg duravg scmin durmin scmax durmax scdeviat durdeviat cid*/
00169 void output(void)
00170 {
00171     int i;
00172     for(i=0;i<MAX_SHEET*MAX_EXO;i++) {
00173        if(shdata[i].newcnt<=0) continue;
00174        stati(shdata+i);
00175        printf(":S %2d %2d %4d %4d \
00176 %4.0f %4.0f %5.2f %5.2f \
00177 %5.2f %4.1f %5.2f %5.1f \
00178 %5.2f %5.2f %4.1f\n",
00179               i/MAX_EXO+1,i%MAX_EXO+1,
00180               shdata[i].newcnt, shdata[i].scorecnt,
00181               scsum, dursum,
00182               scavg, duravg,
00183               scmin,durmin,scmax,durmax,
00184               scdeviat, durdeviat,
00185               cid);
00186     }
00187     for(i=0;i<MAX_EXAM*MAX_EXO;i++) {
00188        if(examdata[i].newcnt<=0) continue;
00189        stati(examdata+i);
00190        printf(":E %2d %2d %4d %4d \
00191 %4.0f %4.0f %5.2f %5.2f \
00192 %5.2f %4.1f %5.2f %5.1f \
00193 %5.2f %5.2f %4.1f\n",
00194               i/MAX_EXO+1,i%MAX_EXO+1,
00195               examdata[i].newcnt, examdata[i].scorecnt,
00196               scsum, dursum,
00197               scavg, duravg,
00198               scmin,durmin,scmax,durmax,
00199               scdeviat, durdeviat,
00200               cid);
00201     }
00202 }
00203 
00204 int main()
00205 {
00206     char cla[MAX_LINELEN+1];
00207     char *c1, *c2;
00208     char *sdata, *cdata;
00209     
00210     memset(shdata,0,sizeof(shdata)); memset(examdata,0,sizeof(examdata));
00211     dirbase=getenv("exostat_dirbase");
00212     if(dirbase==NULL || *dirbase==0) dirbase="../log/classes";
00213     sdata=getenv("exostat_types");
00214     if(sdata==NULL || *sdata==0) sdata="score noscore";
00215     cdata=getenv("exostat_classes");
00216     if(cdata==NULL || *cdata==0) cdata=getenv("w_wims_class");
00217     if(cdata==NULL || *cdata==0) return -1;
00218     snprintf(types,sizeof(types),"%s",sdata);
00219     snprintf(cla,sizeof(cla),"%s",cdata);
00220     for(c1=cla; *c1; c1++) if(!isalnum(*c1) && *c1!='/') *c1=' ';
00221     for(c1=find_word_start(cla); *c1; c1=find_word_start(c2)) {
00222        c2=find_word_end(c1); if(*c2) *c2++=0;
00223        onedir(c1);
00224     }
00225     output();
00226     return 0;
00227 }
00228