Subversion Repositories wimsdev

Rev

Rev 7079 | Rev 8185 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  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.  
  18. /* Computes class connection count (unit: student-minutes) */
  19.  
  20. #include "../wimsdef.h"
  21. #include "../includes.h"
  22. #include "../Lib/libwims.h"
  23.  
  24.     /* The maximal number of sessions within one day */
  25. #define MAX_SESSIONS (128*1024)
  26.     /* The maximal number of classes within one day */
  27. #define MAX_CLASSES 8192
  28.     /* At least these minutes will be counted for each session */
  29. #define MIN_CONNECT 2
  30.     /* Add this number of minutes to each session */
  31. #define MIN_ADD 1
  32.     /* Accounting discontinues after this number of idle minutes */
  33. #define MAX_LAPSE 15
  34.  
  35. struct {
  36.     char s[4], u[32];
  37.     int cl, start, end, cnt;
  38. } ses[MAX_SESSIONS];
  39. int sescnt;
  40.  
  41. char *datestr;
  42.  
  43. struct cls {
  44.     int cl, cnt;
  45. } cls[MAX_CLASSES];
  46. int clscnt;
  47.  
  48. /*
  49. void *xmalloc(size_t n)
  50. {
  51.     void *p;
  52.     p=malloc(n);
  53.     if(p==NULL) {
  54.     fprintf(stderr,"Malloc failure."); exit(1);
  55.     }
  56.     return p;
  57. }
  58. */
  59.     /* Points to the end of the word */
  60. /*
  61. char *find_word_end(char *p)
  62. {
  63.     int i;
  64.     for(i=0;!isspace(*p) && *p!=0 && i<MAX_LINELEN; p++,i++);
  65.     return p;
  66. }
  67. */
  68.     /* Strips leading spaces */
  69. /*
  70. char *find_word_start(char *p)
  71. {
  72.     int i;
  73.     for(i=0; isspace(*p) && i<MAX_LINELEN; p++,i++);
  74.     return p;
  75. }
  76. */
  77.     /* Read/write to a file with variable parms to print filename */
  78. void accessfile(char *content, char *type, char *s,...)
  79. {
  80.     va_list vp;
  81.     char buf[MAX_LINELEN+1];
  82.     FILE *f;
  83.     int l;
  84.  
  85.     va_start(vp,s);
  86.     vsnprintf(buf,sizeof(buf),s,vp);
  87.     va_end(vp);
  88.     f=fopen(buf,type); if(f==NULL) {
  89.     if(*type=='r') content[0]=0; return;
  90.     }
  91.     switch(*type) {
  92.     case 'a':
  93.     case 'w': {
  94.         l=strlen(content); fwrite(content,1,l,f); break;
  95.     }
  96.     case 'r': {
  97.         l=fread(content,1,MAX_LINELEN-1,f);
  98.         if(l>0 && l<MAX_LINELEN) content[l]=0;
  99.         else content[0]=0;
  100.         break;
  101.     }
  102.     default: {
  103.         content[0]=0; break;
  104.     }
  105.     }
  106.     fclose(f);
  107. }
  108.  
  109. /* returns -1 if error */
  110. /*
  111. long int filelength(char *fn,...)
  112. {
  113.     char buf[4096];
  114.     va_list vp;
  115.     struct stat st;
  116.     int l;
  117.  
  118.     va_start(vp,fn);
  119.     vsnprintf(buf,sizeof(buf),fn,vp); va_end(vp);
  120.     l=stat(buf,&st); if(l) return -1;
  121.     return st.st_size;
  122. }
  123. */
  124.     /* recursively generate a directory structure */
  125. void mkdirs2(char *s)
  126. {
  127.     struct stat st;
  128.     char *buf;
  129.     if(stat(s,&st)==-1) {
  130.     if(strrchr(s,'/')!=NULL) {
  131.         buf=xmalloc(strlen(s)+1);
  132.         ovlstrcpy(buf,s); *strrchr(buf,'/')=0;
  133.         mkdirs2(buf); free(buf);
  134.     }
  135.     mkdir(s,-1);
  136.     }
  137. }
  138.  
  139. void oneline(char *p)
  140. {
  141.     char tbuf[8], sbuf[8], ubuf[256], cbuf[64];
  142.     char *p1, *p2;
  143.     int i,t,cl;
  144.     memmove(tbuf,p+9,6); tbuf[2]=tbuf[5]=0;
  145.     t=atoi(tbuf)*60+atoi(tbuf+3);
  146.     memmove(sbuf,p+18,4); sbuf[4]=0;
  147.     p1=strchr(p,','); if(p1==NULL) return;
  148.     if(!isdigit(*(p1+1))) return;
  149.     snprintf(cbuf,sizeof(cbuf),"%s",p1+1);
  150.     for(p2=cbuf;isdigit(*p2); p2++){};
  151.     *p2=0; cl=atoi(cbuf);
  152.     *p1=0; for(p1--;p1>p && !isspace(*(p1-1)); p1--);
  153.     snprintf(ubuf,sizeof(ubuf),"%s",p1);
  154.     for(i=0;i<sescnt;i++) {
  155.     if(cl==ses[i].cl && memcmp(sbuf,ses[i].s,4)==0 &&
  156.        ses[i].end>=t-MAX_LAPSE) {
  157.         ses[i].end=t; return;
  158.     }
  159.     }
  160.     if(sescnt>=MAX_SESSIONS) return;
  161.     memmove(ses[sescnt].s,sbuf,4); ses[sescnt].cl=cl;
  162.     ses[sescnt].start=ses[sescnt].end=t;
  163.     snprintf(ses[sescnt].u,sizeof(ses[sescnt].u),"%s",ubuf);
  164.     sescnt++;
  165. }
  166.  
  167. void onefile(char *fname)
  168. {
  169.     FILE *f;
  170.     long l;
  171.     char *fbuf, *p1, *p2, *p3;
  172.     l=filelength(fname); if(l<=0) return;
  173.     f=fopen(fname,"r"); if(f==NULL) return;
  174.     fbuf=xmalloc(l+16); (void)fread(fbuf,1,l,f); fclose(f); fbuf[l]=0;
  175.     for(p1=fbuf; *p1; p1=p2) {
  176.     p2=strchr(p1,'\n'); if(p2==NULL) p2=p1+strlen(p1); else *p2++=0;
  177.     p3=strchr(p1,','); if(p3==NULL) continue;
  178.     if(strncmp(p1,datestr,8)!=0) continue;
  179.     oneline(p1);
  180.     }
  181. }
  182.  
  183. void classaccount(void)
  184. {
  185.     int i,j;
  186.     clscnt=0;
  187.     for(i=0;i<sescnt;i++) {
  188.     ses[i].cnt=ses[i].end-ses[i].start+MIN_ADD;
  189.     if(ses[i].cnt<MIN_CONNECT) ses[i].cnt=MIN_CONNECT;
  190.     for(j=0;j<clscnt && ses[i].cl!=cls[j].cl;j++);
  191.     if(j<clscnt) cls[j].cnt+=ses[i].cnt;
  192.     else if(clscnt<MAX_CLASSES) {
  193.         cls[clscnt].cl=ses[i].cl;
  194.         cls[clscnt].cnt=ses[i].cnt;
  195.         clscnt++;
  196.     }
  197.     }
  198. }
  199.  
  200. int clscmp(const void *c1, const void *c2)
  201. {
  202.     struct cls *cl1, *cl2;
  203.     cl1=(struct cls *) c1; cl2=(struct cls *) c2;
  204.     return cl1->cl-cl2->cl;
  205. }
  206.  
  207. void output(void)
  208. {
  209.     char *p, buf[1024], dbuf[1024];
  210.     int i,t;
  211.     p=getenv("ccsum_outdir"); if(p==NULL || *p==0) return;
  212.     for(i=0;i<sescnt;i++) {
  213.     snprintf(dbuf,sizeof(dbuf),"%s/%d",p,ses[i].cl);
  214.     mkdirs2(dbuf);
  215.     snprintf(buf,sizeof(buf),"%s.%02d:%02d %d\n",
  216.          datestr,ses[i].start/60,ses[i].start%60,ses[i].cnt);
  217.     accessfile(buf,"a","%s/%s",dbuf,ses[i].u);
  218.     }
  219.     snprintf(dbuf,sizeof(dbuf),"%s/bydate/%.4s",p,datestr);
  220.     mkdirs2(dbuf);
  221.     snprintf(dbuf+strlen(dbuf),sizeof(dbuf)-strlen(dbuf),"/%.2s",datestr+4);
  222.     t=0;
  223.     qsort(cls,clscnt,sizeof(cls[0]),clscmp);
  224.     for(i=0;i<clscnt;i++) {
  225.     snprintf(buf,sizeof(buf),"%s %d\n",datestr,cls[i].cnt);
  226.     accessfile(buf,"a","%s/%d/.total",p,cls[i].cl);
  227.     snprintf(buf,sizeof(buf),"%s %d %d\n",datestr+4,cls[i].cl,cls[i].cnt);
  228.     accessfile(buf,"a","%s",dbuf);
  229.     t+=cls[i].cnt;
  230.     }
  231.     snprintf(buf,sizeof(buf),"%s %d %d\n",datestr,t,(t+30)/60);
  232.     accessfile(buf,"a","%s/done",p);
  233. }
  234.  
  235. int main(int argc, char *argv[])
  236. {
  237.     sescnt=0;
  238.     if(argc<2) return 1;
  239.     datestr=getenv("ccsum_date");
  240.     if(datestr==NULL || strlen(datestr)!=8) return 2;
  241.     onefile(argv[1]);
  242.     classaccount();
  243.     output();
  244.     return 0;
  245. }
  246.  
  247.