Subversion Repositories wimsdev

Rev

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