Rev 3923 | 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 | /* Caches and its management */ |
||
19 | |||
20 | /* General information of an exercise. Size: 10 bytes. */ |
||
21 | typedef struct exodata { |
||
22 | unsigned short int num; |
||
23 | float weight, require; |
||
24 | } exodata; |
||
25 | |||
26 | struct classdata { |
||
27 | char name[MAX_CLASSLEN+1]; |
||
28 | time_t start, last, modif; |
||
29 | int exocnt, examcnt, examstart, access; |
||
30 | struct exodata exos[MAX_CLASSEXOS]; |
||
31 | char ctbuf[CTBUFLEN]; |
||
32 | short int ctptr[MAX_EXOS]; |
||
33 | } classdata[MAX_CLASSCACHE]; |
||
34 | |||
35 | struct classcache { |
||
36 | struct classdata *ptr; |
||
37 | } classcache[MAX_CLASSCACHE]; |
||
38 | int classcaches; |
||
39 | |||
40 | struct sheetdata { |
||
41 | char buffer[SHEETBUFLEN]; |
||
42 | int name,header,status,exocnt,exo[MAX_EXOS]; |
||
43 | time_t start, last; |
||
44 | int access; |
||
45 | } sheetdata[MAX_SHEETCACHE]; |
||
46 | |||
47 | struct sheetcache { |
||
48 | struct sheetdata *ptr; |
||
49 | } sheetcache[MAX_SHEETCACHE]; |
||
50 | int sheetcaches; |
||
51 | |||
52 | /* searches a list. Returns index if found, -1 if nomatch. |
||
53 | * Uses binary search, list must be sorted. */ |
||
54 | int search_data(void *list, int items, size_t item_size, unsigned short int t) |
||
55 | { |
||
56 | int i1,i2,j,k; |
||
57 | unsigned short int *p; |
||
58 | |||
59 | if(items<=0) return -1; |
||
60 | j=0; p=list; k=*p-t; |
||
61 | if(k==0) return k; if(k>0) return -1; |
||
62 | p=list+(items-1)*item_size; |
||
63 | k=*p-t; if(k==0) return items-1; if(k<0) return ~items; |
||
64 | for(i1=0,i2=items-1;i2>i1+1;) { |
||
65 | j=(i2+i1)/2; |
||
66 | p=list+(j*item_size); |
||
67 | k=*p-t; |
||
68 | if(k==0) return j; |
||
69 | if(k>0) {i2=j; continue;} |
||
70 | if(k<0) {i1=j; continue;} |
||
71 | } |
||
72 | return ~i2; |
||
73 | } |
||
74 | |||
75 | /* remove old cache items */ |
||
76 | void cleancache(void) |
||
77 | { |
||
78 | int i; |
||
79 | time_t now; |
||
80 | struct classdata *cd; |
||
81 | struct sheetdata *sd; |
||
82 | now=time(NULL); |
||
83 | for(i=0;i<classcaches;i++) { |
||
84 | cd=classcache[i].ptr; |
||
85 | if(now<cd->start+CLASSCACHE_DELAY) continue; |
||
86 | cd->access=0; |
||
87 | memmove(classcache+i,classcache+i+1,(classcaches-i-1)*sizeof(classcache[0])); |
||
88 | classcaches--; |
||
89 | } |
||
90 | for(i=0;i<sheetcaches;i++) { |
||
91 | sd=sheetcache[i].ptr; |
||
92 | if(now<sd->start+SHEETCACHE_DELAY) continue; |
||
93 | sd->access=0; |
||
94 | memmove(sheetcache+i,sheetcache+i+1,(sheetcaches-i-1)*sizeof(sheetcache[0])); |
||
95 | sheetcaches--; |
||
96 | } |
||
97 | } |
||
98 | |||
99 | /* Locate the cache number of a class */ |
||
100 | struct classdata *getclasscache(char *cl) |
||
101 | { |
||
102 | int i,j,k,l,m,n, oldest; |
||
103 | struct stat st; |
||
104 | struct classdata *cd; |
||
105 | char buf[MAX_LINELEN+1], buf2[MAX_LINELEN+1]; |
||
106 | char *p1, *p2, *q1, *q2; |
||
107 | time_t tt; |
||
108 | tt=0, oldest=0; |
||
109 | for(i=0;i<classcaches;i++) { |
||
110 | cd=classcache[i].ptr; |
||
111 | if(tt>cd->start) {tt=cd->start; oldest=i;} |
||
112 | if(strcmp(cd->name,cl)==0) { |
||
113 | cd->access++; |
||
114 | return cd; |
||
115 | } |
||
116 | } |
||
117 | if(classcaches>=MAX_CLASSCACHE) { |
||
118 | i=oldest;cd=classcache[i].ptr; |
||
119 | cd->access=0; |
||
120 | memmove(classcache+i,classcache+i+1,(classcaches-i-1)*sizeof(classcache[0])); |
||
121 | classcaches--; |
||
122 | } |
||
123 | for(i=0;i<MAX_CLASSCACHE && classdata[i].access>0; i++); |
||
124 | if(i>classcaches) return NULL; |
||
125 | cd=classdata+i; cd->access=1; |
||
126 | classcache[classcaches++].ptr=cd; |
||
127 | snprintf(cd->name,sizeof(cd->name),"%s",cl); |
||
128 | cd->start=time(NULL); cd->exocnt=0; |
||
129 | /* Now get the exo data */ |
||
130 | accessfile(buf,"r","sheets/.require"); |
||
131 | for(i=k=0,p1=buf; *p1; i++,p1=p2) { |
||
132 | p2=strchr(p1,'\n'); if(p2) *p2++=0; else p2=p1+strlen(p1); |
||
133 | for(j=0,q1=find_word_start(p1); *q1 && k<MAX_CLASSEXOS; j++,q1=find_word_start(q2)) { |
||
134 | q2=find_word_end(q1); if(*q2) *q2++=0; |
||
135 | cd->exos[k].num=(i<<8)+j;cd->exos[k].require=atof(q1); |
||
136 | cd->exos[k].weight=0; |
||
137 | k++; |
||
138 | } |
||
139 | |||
140 | } |
||
141 | if(k>=MAX_CLASSEXOS) return NULL; |
||
142 | cd->exocnt=k; cd->examstart=k; cd->modif=0; |
||
143 | accessfile(buf,"r","sheets/.weight"); |
||
144 | for(i=k=0,p1=buf; *p1; i++,p1=p2) { |
||
145 | p2=strchr(p1,'\n'); if(p2) *p2++=0; else p2=p1+strlen(p1); |
||
146 | for(j=0,q1=find_word_start(p1); *q1 && k<MAX_CLASSEXOS; j++,q1=find_word_start(q2)) { |
||
147 | q2=find_word_end(q1); if(*q2) *q2++=0; |
||
148 | if(cd->exos[k].num==(i<<8)+j) { |
||
149 | cd->exos[k].weight=atof(q1); |
||
150 | k++; |
||
151 | } |
||
152 | else while(k<cd->exocnt && cd->exos[k].num<(i<<8)+j) k++; |
||
153 | } |
||
154 | } |
||
155 | if(stat("exams/.exams",&st)==0) cd->modif=st.st_mtime; else return cd; |
||
156 | accessfile(buf,"r","exams/.exams"); |
||
157 | if(buf[0]==0) return cd; |
||
158 | if(buf[0]==':') p1=buf-1; else p1=strstr(buf,"\n:"); |
||
159 | for(n=m=0,k=cd->exocnt; p1 && k<MAX_CLASSEXOS && m<MAX_EXOS; p1=p2,m++) { |
||
160 | p1+=2; |
||
161 | p2=strstr(p1,"\n:"); if(p2) *p2=0; |
||
162 | if(*find_word_start(p1)<'1') continue; /* status */ |
||
163 | fnd_line(p1,3,buf2); if(buf2[0]==0) continue; |
||
164 | q1=find_word_start(buf2); q2=find_word_end(q1); |
||
165 | if(*q2) *q2++=0; |
||
166 | q2=find_word_start(q2); *find_word_end(q2)=0; |
||
167 | i=atoi(q1); j=atoi(q2); if(i<=0 || j<=0) continue; |
||
168 | cd->exos[k].num=0xFF00+m; |
||
169 | cd->exos[k].weight=i; cd->exos[k].require=j; /* weight: duration. require: retries */ |
||
170 | fnd_line(p1,6,buf2); q1=find_word_start(buf2); |
||
171 | singlespace(q1); strip_trailing_spaces(q1); |
||
172 | cd->ctptr[k-cd->exocnt]=n; cd->ctbuf[n]=0; |
||
173 | if(n+strlen(q1)>CTBUFLEN-MAX_EXOS-16) *q1=0; /* silent truncation */ |
||
174 | l=strlen(q1)+1; memmove(cd->ctbuf+n,q1,l); n+=l; |
||
175 | k++; |
||
176 | } |
||
177 | cd->examcnt=k-cd->exocnt; cd->exocnt=k; |
||
178 | return cd; |
||
179 | } |
||
180 | |||
181 | /* prepare cache for a sheet */ |
||
182 | struct sheetata *getsheetcache(char *cl, char *sh) |
||
183 | { |
||
184 | |||
185 | |||
186 | |||
187 | return NULL; |
||
188 | } |
||
189 |