Back to index

wims  3.65+svn20090927
ccsum.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        /* Computes class connection count (unit: student-minutes) */
00019 
00020 #include "../wimsdef.h"
00021 #include "../includes.h"
00022 
00023        /* The maximal number of sessions within one day */
00024 #define MAX_SESSIONS (128*1024)
00025        /* The maximal number of classes within one day */
00026 #define MAX_CLASSES 8192
00027        /* At least these minutes will be counted for each session */
00028 #define MIN_CONNECT 2
00029        /* Add this number of minutes to each session */
00030 #define MIN_ADD 1
00031        /* Accounting discontinues after this number of idle minutes */
00032 #define MAX_LAPSE 15
00033 
00034 struct {
00035     char s[4], u[32];
00036     int cl, start, end, cnt;
00037 } ses[MAX_SESSIONS];
00038 int sescnt;
00039 
00040 char *datestr;
00041 
00042 struct cls {
00043     int cl, cnt;
00044 } cls[MAX_CLASSES];
00045 int clscnt;
00046 
00047 void *xmalloc(size_t n)
00048 {
00049     void *p;
00050     p=malloc(n);
00051     if(p==NULL) {
00052        fprintf(stderr,"Malloc failure."); exit(1);
00053     }
00054     return p;
00055 }
00056 
00057        /* Points to the end of the word */
00058 char *find_word_end(char *p)
00059 {
00060     int i;
00061     for(i=0;!isspace(*p) && *p!=0 && i<MAX_LINELEN; p++,i++);
00062     return p;
00063 }
00064 
00065        /* Strips leading spaces */
00066 char *find_word_start(char *p)
00067 {
00068     int i;
00069     for(i=0; isspace(*p) && i<MAX_LINELEN; p++,i++);
00070     return p;
00071 }
00072 
00073        /* Read/write to a file with variable parms to print filename */
00074 void accessfile(char *content, char *type, char *s,...)
00075 {
00076     va_list vp;
00077     char buf[MAX_LINELEN+1];
00078     FILE *f;
00079     int l;
00080 
00081     va_start(vp,s);
00082     vsnprintf(buf,sizeof(buf),s,vp);
00083     va_end(vp);
00084     f=fopen(buf,type); if(f==NULL) {
00085        if(*type=='r') content[0]=0; return;
00086     }
00087     switch(*type) {
00088        case 'a':
00089        case 'w': {
00090            l=strlen(content); fwrite(content,1,l,f); break;
00091        }
00092        case 'r': {
00093            l=fread(content,1,MAX_LINELEN-1,f);
00094            if(l>0 && l<MAX_LINELEN) content[l]=0;
00095            else content[0]=0;
00096            break;
00097        }
00098        default: {
00099            content[0]=0; break;
00100        }
00101     }
00102     fclose(f);
00103 }
00104 
00105        /* returns -1 if error */
00106 long int filelength(char *fn,...)
00107 {
00108     char buf[4096];
00109     va_list vp;
00110     struct stat st;
00111     int l;
00112     
00113     va_start(vp,fn);
00114     vsnprintf(buf,sizeof(buf),fn,vp); va_end(vp);
00115     l=stat(buf,&st); if(l) return -1;
00116     return st.st_size;
00117 }
00118 
00119        /* recursively generate a directory structure */
00120 void mkdirs(char *s)
00121 {
00122     struct stat st;
00123     char *buf;
00124     if(stat(s,&st)==-1) {
00125        if(strrchr(s,'/')!=NULL) {
00126            buf=xmalloc(strlen(s)+1);
00127            strcpy(buf,s); *strrchr(buf,'/')=0;
00128            mkdirs(buf); free(buf);
00129        }
00130        mkdir(s,-1);
00131     }
00132 }
00133 
00134 void oneline(char *p)
00135 {
00136     char tbuf[8], sbuf[8], ubuf[256], cbuf[64];
00137     char *p1, *p2;
00138     int i,t,cl;
00139     memmove(tbuf,p+9,6); tbuf[2]=tbuf[5]=0;
00140     t=atoi(tbuf)*60+atoi(tbuf+3);
00141     memmove(sbuf,p+18,4); sbuf[4]=0;
00142     p1=strchr(p,','); if(p1==NULL) return;
00143     if(!isdigit(*(p1+1))) return;
00144     snprintf(cbuf,sizeof(cbuf),"%s",p1+1);
00145     for(p2=cbuf;isdigit(*p2); p2++); *p2=0; cl=atoi(cbuf);
00146     *p1=0; for(p1--;p1>p && !isspace(*(p1-1)); p1--);
00147     snprintf(ubuf,sizeof(ubuf),"%s",p1);
00148     for(i=0;i<sescnt;i++) {
00149        if(cl==ses[i].cl && memcmp(sbuf,ses[i].s,4)==0 &&
00150           ses[i].end>=t-MAX_LAPSE) {
00151            ses[i].end=t; return;
00152        }
00153     }
00154     if(sescnt>=MAX_SESSIONS) return;
00155     memmove(ses[sescnt].s,sbuf,4); ses[sescnt].cl=cl;
00156     ses[sescnt].start=ses[sescnt].end=t;
00157     snprintf(ses[sescnt].u,sizeof(ses[sescnt].u),"%s",ubuf);
00158     sescnt++;
00159 }
00160 
00161 void onefile(char *fname)
00162 {
00163     FILE *f;
00164     long l;
00165     char *fbuf, *p1, *p2, *p3;
00166     l=filelength(fname); if(l<=0) return;
00167     f=fopen(fname,"r"); if(f==NULL) return;
00168     fbuf=xmalloc(l+16); fread(fbuf,1,l,f); fclose(f); fbuf[l]=0;
00169     for(p1=fbuf; *p1; p1=p2) {
00170        p2=strchr(p1,'\n'); if(p2==NULL) p2=p1+strlen(p1); else *p2++=0;
00171        p3=strchr(p1,','); if(p3==NULL) continue;
00172        if(strncmp(p1,datestr,8)!=0) continue;
00173        oneline(p1);
00174     }
00175 }
00176 
00177 void classaccount(void)
00178 {
00179     int i,j;
00180     clscnt=0;
00181     for(i=0;i<sescnt;i++) {
00182        ses[i].cnt=ses[i].end-ses[i].start+MIN_ADD;
00183        if(ses[i].cnt<MIN_CONNECT) ses[i].cnt=MIN_CONNECT;
00184        for(j=0;j<clscnt && ses[i].cl!=cls[j].cl;j++);
00185        if(j<clscnt) cls[j].cnt+=ses[i].cnt;
00186        else if(clscnt<MAX_CLASSES) {
00187            cls[clscnt].cl=ses[i].cl;
00188            cls[clscnt].cnt=ses[i].cnt;
00189            clscnt++;
00190        }
00191     }
00192 }
00193 
00194 int clscmp(const void *c1, const void *c2)
00195 {
00196     struct cls *cl1, *cl2;
00197     cl1=(struct cls *) c1; cl2=(struct cls *) c2;
00198     return cl1->cl-cl2->cl;
00199 }
00200 
00201 void output(void)
00202 {
00203     char *p, buf[1024], dbuf[1024];
00204     int i,t;
00205     p=getenv("ccsum_outdir"); if(p==NULL || *p==0) return;
00206     for(i=0;i<sescnt;i++) {
00207        snprintf(dbuf,sizeof(dbuf),"%s/%d",p,ses[i].cl);
00208        mkdirs(dbuf);
00209        snprintf(buf,sizeof(buf),"%s.%02d:%02d %d\n",
00210                datestr,ses[i].start/60,ses[i].start%60,ses[i].cnt);
00211        accessfile(buf,"a","%s/%s",dbuf,ses[i].u);
00212     }
00213     snprintf(dbuf,sizeof(dbuf),"%s/bydate/%.4s",p,datestr);
00214     mkdirs(dbuf);
00215     snprintf(dbuf+strlen(dbuf),sizeof(dbuf)-strlen(dbuf),"/%.2s",datestr+4);
00216     t=0;
00217     qsort(cls,clscnt,sizeof(cls[0]),clscmp);
00218     for(i=0;i<clscnt;i++) {
00219        snprintf(buf,sizeof(buf),"%s %d\n",datestr,cls[i].cnt);
00220        accessfile(buf,"a","%s/%d/.total",p,cls[i].cl);
00221        snprintf(buf,sizeof(buf),"%s %d %d\n",datestr+4,cls[i].cl,cls[i].cnt);
00222        accessfile(buf,"a","%s",dbuf);
00223        t+=cls[i].cnt;
00224     }
00225     snprintf(buf,sizeof(buf),"%s %d %d\n",datestr,t,(t+30)/60);
00226     accessfile(buf,"a","%s/done",p);
00227 }
00228 
00229 int main(int argc, char *argv[])
00230 {
00231     sescnt=0;
00232     if(argc<2) return 1;
00233     datestr=getenv("ccsum_date");
00234     if(datestr==NULL || strlen(datestr)!=8) return 2;
00235     onefile(argv[1]);
00236     classaccount();
00237     output();
00238     return 0;
00239 }
00240