Rev 7079 | Rev 8149 | Go to most recent revision | 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 | |||
8100 | bpr | 18 | /* Computes class connection count (unit: student-minutes) */ |
10 | reyssat | 19 | |
20 | #include "../wimsdef.h" |
||
21 | #include "../includes.h" |
||
8100 | bpr | 22 | #include "../Lib/libwims.h" |
10 | reyssat | 23 | |
7079 | bpr | 24 | /* The maximal number of sessions within one day */ |
10 | reyssat | 25 | #define MAX_SESSIONS (128*1024) |
7079 | bpr | 26 | /* The maximal number of classes within one day */ |
10 | reyssat | 27 | #define MAX_CLASSES 8192 |
7079 | bpr | 28 | /* At least these minutes will be counted for each session */ |
10 | reyssat | 29 | #define MIN_CONNECT 2 |
7079 | bpr | 30 | /* Add this number of minutes to each session */ |
10 | reyssat | 31 | #define MIN_ADD 1 |
7079 | bpr | 32 | /* Accounting discontinues after this number of idle minutes */ |
10 | reyssat | 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 | |||
8100 | bpr | 48 | /* |
10 | reyssat | 49 | void *xmalloc(size_t n) |
50 | { |
||
51 | void *p; |
||
52 | p=malloc(n); |
||
53 | if(p==NULL) { |
||
7079 | bpr | 54 | fprintf(stderr,"Malloc failure."); exit(1); |
10 | reyssat | 55 | } |
56 | return p; |
||
57 | } |
||
8100 | bpr | 58 | */ |
7079 | bpr | 59 | /* Points to the end of the word */ |
8100 | bpr | 60 | /* |
10 | reyssat | 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 | } |
||
8100 | bpr | 67 | */ |
7079 | bpr | 68 | /* Strips leading spaces */ |
8100 | bpr | 69 | /* |
10 | reyssat | 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 | } |
||
8100 | bpr | 76 | */ |
7079 | bpr | 77 | /* Read/write to a file with variable parms to print filename */ |
10 | reyssat | 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) { |
||
7079 | bpr | 89 | if(*type=='r') content[0]=0; return; |
10 | reyssat | 90 | } |
91 | switch(*type) { |
||
7079 | bpr | 92 | case 'a': |
93 | case 'w': { |
||
94 | l=strlen(content); fwrite(content,1,l,f); break; |
||
10 | reyssat | 95 | } |
7079 | bpr | 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 | } |
||
10 | reyssat | 106 | fclose(f); |
107 | } |
||
108 | |||
8100 | bpr | 109 | /* returns -1 if error */ |
110 | /* |
||
10 | reyssat | 111 | long int filelength(char *fn,...) |
112 | { |
||
113 | char buf[4096]; |
||
114 | va_list vp; |
||
115 | struct stat st; |
||
116 | int l; |
||
7079 | bpr | 117 | |
10 | reyssat | 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 | } |
||
8100 | bpr | 123 | */ |
7079 | bpr | 124 | /* recursively generate a directory structure */ |
8100 | bpr | 125 | void mkdirs2(char *s) |
10 | reyssat | 126 | { |
127 | struct stat st; |
||
128 | char *buf; |
||
129 | if(stat(s,&st)==-1) { |
||
7079 | bpr | 130 | if(strrchr(s,'/')!=NULL) { |
131 | buf=xmalloc(strlen(s)+1); |
||
132 | ovlstrcpy(buf,s); *strrchr(buf,'/')=0; |
||
8100 | bpr | 133 | mkdirs2(buf); free(buf); |
10 | reyssat | 134 | } |
7079 | bpr | 135 | mkdir(s,-1); |
136 | } |
||
10 | reyssat | 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); |
||
7079 | bpr | 150 | for(p2=cbuf;isdigit(*p2); p2++){}; |
7076 | obado | 151 | *p2=0; cl=atoi(cbuf); |
10 | reyssat | 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++) { |
||
7079 | bpr | 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; |
||
10 | reyssat | 158 | } |
7079 | bpr | 159 | } |
10 | reyssat | 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; |
||
3840 | kbelabas | 174 | fbuf=xmalloc(l+16); (void)fread(fbuf,1,l,f); fclose(f); fbuf[l]=0; |
10 | reyssat | 175 | for(p1=fbuf; *p1; p1=p2) { |
7079 | bpr | 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); |
||
10 | reyssat | 180 | } |
181 | } |
||
182 | |||
183 | void classaccount(void) |
||
184 | { |
||
185 | int i,j; |
||
186 | clscnt=0; |
||
187 | for(i=0;i<sescnt;i++) { |
||
7079 | bpr | 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++; |
||
10 | reyssat | 196 | } |
7079 | bpr | 197 | } |
10 | reyssat | 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++) { |
||
7079 | bpr | 213 | snprintf(dbuf,sizeof(dbuf),"%s/%d",p,ses[i].cl); |
8100 | bpr | 214 | mkdirs2(dbuf); |
7079 | bpr | 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); |
||
10 | reyssat | 218 | } |
219 | snprintf(dbuf,sizeof(dbuf),"%s/bydate/%.4s",p,datestr); |
||
8100 | bpr | 220 | mkdirs2(dbuf); |
10 | reyssat | 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++) { |
||
7079 | bpr | 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; |
||
10 | reyssat | 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 |