e9a26c3bae3f08b7bbdad65c29a35b987f65553b
[irssistats] / irssistats.c
1 /* Usage: cat /path/to/file.log | ./irssistats > /path/to/file.html */
2
3 /* Config */
4 #define CHANNEL "#channel"
5 #define MAINTAINER "maintainer"
6
7 /* Language */
8 #define HEADER "Statistiques de %s par %s"
9 #define LEGEND "Légende"
10 #define LASTDAYS "Statistiques des derniers jours"
11 #define TOPHOURS "Statistiques horaires"
12 #define TOPUSERS "Personnes les plus actives"
13 #define OTHERS "Il reste %d personnes non classées..."
14 #define NBLINES "lignes"
15 #define NICK "nick"
16 #define AVGLETTERS "lettres/lignes"
17 #define HOURS "heures"
18 #define QUOTE "message aléatoire"
19 #define RANDTOPICS "Quelques topics"
20 #define CHANGEDBY "changé par"
21 #define NEWTOPIC "nouveau topic"
22 #define RANDURLS "Quelques URLs"
23 #define POSTEDBY "postée par"
24 #define POSTEDURL "URL"
25 #define BIGNUMBERS "Quelques grands nombres..."
26 #define TIME "%d lignes traitées en %d secondes"
27 #define FOOTER "Statistiques générées par"
28
29 /* Colors */
30 #define BGCOLOR "#FFFFFF"
31 #define TEXT "#000000"
32 #define LINK "#0000EE"
33 #define VLINK "#551A8B"
34 #define ALINK "#FF0000"
35 #define TITLE1 "#000000"
36 #define TITLE2 "#000000"
37 #define BGTABLE "#EEEEEE"
38 #define BGTITLE "#FFEEEE"
39
40 /* Dark Theme... */
41 /*
42 #define BGCOLOR "#000000"
43 #define TEXT "#FFFFFF"
44 #define LINK "#AAAAFF"
45 #define VLINK "#CCCCDD"
46 #define ALINK "#FFAAAA"
47 #define TITLE1 "#AAAAFF"
48 #define TITLE2 "#FFAAAA"
49 #define BGTABLE "#225522"
50 #define BGTITLE "#552222"
51 */
52
53
54 /* irssistats */
55 #define VERSION "0.1"
56 #define URL "http://royale.zerezo.com/programmation/irssistats/"
57
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <time.h>
62 #include <string.h>
63
64 #define MAXUSERS 2000
65 #define MAXNICKLENGTH 50
66 #define MAXLINELENGTH 2000
67
68 struct 
69 {
70   char nick[MAXNICKLENGTH];
71   int lines;
72   int letters;
73   int hours[4];
74   char quote[MAXLINELENGTH];
75 } users[MAXUSERS];
76 int nbusers=0;
77
78 struct
79 {
80   char nick[MAXNICKLENGTH];
81   char url[MAXLINELENGTH];
82 } urls[5];
83 int nburls=0;
84
85 struct
86
87   char nick[MAXNICKLENGTH];
88   char topic[MAXLINELENGTH];
89 } topics[5];
90 int nbtopics=0;
91
92 struct
93 {
94   int lines;
95   int hours[4];
96 } lastdays[31];
97 int days=0;
98
99 int hours[24];
100 int lines=0;
101
102 void unhtml(char *string) /* replace < and > by { and } */
103 {
104   while (*string!='\0')
105   {
106     if (*string=='<') *string='{';
107     if (*string=='>') *string='}';
108     string++;
109   }
110   return;
111 }
112
113 int main(int argc,char *argv[])
114 {
115   int i,j;
116   int max,user,hour;
117   time_t debut;
118   int totallines=0;
119   int pos=0;
120   char c;
121   char *nick,*message;
122   char line[MAXLINELENGTH];
123   
124   /*** LOG ***/
125   
126   srand(debut=time(NULL));
127   fprintf(stderr,"working");
128   while (!feof(stdin))
129   {
130     c=getchar();
131     line[pos++]=c;
132     if (pos>=MAXLINELENGTH) { fprintf(stderr,"line too long\n"); exit(1); }
133     if (c=='\n')
134     {
135       totallines++;
136       if (totallines%10000==0) { fprintf(stderr,"."); fflush(stdout); }
137       if (strncmp("--- Day changed",line,15)==0) /* --- Day changed Wed May 01 2002 */
138       {
139         for (i=30;i>0;i--)
140         {
141           lastdays[i].lines=lastdays[i-1].lines;
142           for (j=0;j<4;j++) lastdays[i].hours[j]=lastdays[i-1].hours[j];
143         }
144         lastdays[0].lines=0;
145         for (j=0;j<4;j++) lastdays[0].hours[j]=0;
146         days++;
147       }
148       else if (strncmp("-!-",&line[6],3)==0) /* 00:00 -!- Nick changed the topic of #channel to: new topic */
149       {
150         for (i=10;line[i]!=' ';i++);
151         line[i]='\0';
152         nick=&line[10];
153         unhtml(nick);
154         message=&line[i+1];
155         unhtml(message);
156         if (strncmp("changed the topic of",message,20)==0)
157         {
158           for (i=21;message[i]!=':';i++);
159           message=&message[i+2];
160           line[pos-1]='\0';
161           nbtopics++;
162           if ((nbtopics<=5) || (rand()%nbtopics==0))
163           {
164             for (i=4;i>0;i--)
165             {
166               strcpy(topics[i].nick,topics[i-1].nick);
167               strcpy(topics[i].topic,topics[i-1].topic);
168             }
169             strcpy(topics[0].nick,nick);
170             strcpy(topics[0].topic,message);
171           }
172         }
173       }
174       else  /* 00:00 <?Nick> the message */
175       {
176         line[2]='\0';
177         hour=atoi(line);
178         if ((line[6]=='<') && (line[7]!='>'))
179         {
180           for (i=7;line[i]!='>';i++);
181           line[i]='\0';
182           nick=&line[8];
183           unhtml(nick);
184           line[pos-1]='\0';
185           message=&line[i+2];
186           unhtml(message);
187           for (i=0;i<nbusers;i++) if (strcmp(nick,users[i].nick)==0) break;
188           if (i==nbusers)
189           {
190             strcpy(users[nbusers].nick,nick);
191             nbusers++;
192             if (nbusers>=MAXUSERS) { fprintf(stderr,"too many users\n"); exit(1); }
193           }
194           users[i].lines++;
195           users[i].letters+=strlen(message);
196           users[i].hours[hour/6]++;
197           lastdays[0].lines++;
198           lastdays[0].hours[hour/6]++;
199           lines++;
200           hours[hour]++;
201           if (rand()%users[i].lines==0) strncpy(users[i].quote,message,100);
202           if (strncmp("http://",message,7)==0)
203           {
204             for (i=0;(message[i]!=' ') && (i<strlen(message));i++);
205             message[i]='\0';
206             nburls++;
207             if ((nburls<=5) || (rand()%nburls==0))
208             {
209               for (i=4;i>0;i--)
210               {
211                 strcpy(urls[i].nick,urls[i-1].nick);
212                 strcpy(urls[i].url,urls[i-1].url);
213               }
214               strcpy(urls[0].nick,nick);
215               strcpy(urls[0].url,message);
216             }
217           }
218         }
219       }
220       pos=0;
221     }
222   }
223   fprintf(stderr,"done\n");
224
225   /*** HTML ***/
226
227   /* header */
228   printf("<!-- Generated by irssistats %s : %s -->\n\n",VERSION,URL);
229   printf("<html>\n\n<head>\n<base target=\"_blank\">\n<title>");
230   printf(HEADER,CHANNEL,MAINTAINER);
231   printf("</title>\n</head>\n\n");
232   printf("<body bgcolor=\"%s\" text=\"%s\" link=\"%s\" vlink=\"%s\" alink=\"%s\">\n\n<center>\n\n<font color=\"%s\"><h1>",BGCOLOR,TEXT,LINK,VLINK,ALINK,TITLE1);
233   printf(HEADER,CHANNEL,MAINTAINER);
234   printf("</h1></font>\n%s<br>\n<br><br>\n\n",ctime(&debut));
235
236   /* legend */
237   printf("<font color=\"%s\"><h3>%s</h3></font>\n<table bgcolor=%s>\n<tr>\n",TITLE2,LEGEND,BGTABLE);
238   for (i=0;i<4;i++) printf("<td><img src=\"h%d.png\" width=\"40\" height=\"15\"></td><td> : %s %d-%d&nbsp;</td><td width=\"10\"></td>\n",i+1,HOURS,i*6,i*6+5);
239   printf("</tr>\n</table>\n<br><br>\n\n");
240   
241   /* last days */
242   printf("<font color=\"%s\"><h3>%s</h3></font>\n<table>\n<tr>\n",TITLE2,LASTDAYS);
243   max=-1;
244   for (i=30;i>=0;i--) if (lastdays[i].lines>max) max=lastdays[i].lines;
245   for (i=30;i>=0;i--)
246   {
247     printf("<td align=\"center\" valign=\"bottom\"><font size=\"-2\">%d</font><br>",lastdays[i].lines);
248     if (max!=0) for (j=0;j<4;j++) printf("<img src=\"v%d.png\" width=\"15\" height=\"%d\"><br>",j+1,150*lastdays[i].hours[j]/max);
249     printf("</td>\n");
250   }
251   printf("</tr>\n<tr>\n");
252   for (i=30;i>=0;i--)
253     printf("<td align=\"center\" valign=\"center\" bgcolor=\"%s\">%d</td>\n",BGTABLE,i);
254   printf("</tr>\n</table>\n<br><br>\n\n");
255   
256   /* top hours */
257   printf("<font color=\"%s\"><h3>%s</h3></font>\n<table>\n<tr>\n",TITLE2,TOPHOURS);
258   if (lines!=0) for (i=0;i<24;i++)
259     printf("<td align=\"center\" valign=\"bottom\"><font size=\"-2\">%.1f%%</font><br><img src=\"v%d.png\" width=\"15\" height=\"%d\"></td>\n",(float)100*hours[i]/lines,i/6+1,1500*hours[i]/lines);
260   printf("</tr>\n<tr>\n");
261   for (i=0;i<24;i++)
262     printf("<td align=\"center\" valign=\"center\" bgcolor=\"%s\">%d</td>\n",BGTABLE,i);
263   printf("</tr>\n</table>\n<br><br>\n\n");
264   
265   /* top users */
266   printf("<font color=\"%s\"><h3>%s</h3></font>\n",TITLE2,TOPUSERS);
267   printf("<table>\n<tr><td></td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\" colspan=\"2\">%s</td><td bgcolor=\"%s\">%s</td>\n",BGTITLE,NICK,BGTITLE,NBLINES,BGTITLE,HOURS,BGTITLE,AVGLETTERS,BGTITLE,QUOTE);
268   for (i=1;i<=50;i++)
269   {
270     user=-1;
271     max=-1;
272     for (j=0;j<nbusers;j++) if (users[j].lines>max) max=users[user=j].lines;
273     if (user!=-1)
274     {
275       printf("<tr><td bgcolor=\"%s\" align=\"right\">%d</td><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%d</td><td bgcolor=\"%s\">",BGTABLE,i,BGTABLE,users[user].nick,BGTABLE,users[user].lines,BGTABLE);
276       for (j=0;j<4;j++)
277         printf("<img src=\"h%d.png\" width=\"%d\" height=\"15\">",j+1,100*users[user].hours[j]/users[user].lines);
278       printf("</td><td bgcolor=\"%s\">%d</td><td bgcolor=\"%s\"><img src=\"hm.png\" width=\"%d\" height=\"15\"></td><td bgcolor=\"%s\">\"%s\"</td></tr>\n",BGTABLE,users[user].letters/users[user].lines,BGTABLE,users[user].letters/users[user].lines,BGTABLE,users[user].quote);
279       users[user].lines=-1;
280     }    
281   }
282   printf("</table><br>\n");
283   if (nbusers>50) printf(OTHERS,nbusers-50);
284   printf("<br>\n<br><br>\n\n");
285
286   /* random topics */
287   printf("<font color=\"%s\"><h3>%s</h3></font>\n",TITLE2,RANDTOPICS);
288   printf("<table>\n<tr><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td></tr>\n",BGTITLE,CHANGEDBY,BGTITLE,NEWTOPIC);
289   for (i=4;i>=0;i--)
290     printf("<tr><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">\"%s\"</td></tr>\n",BGTABLE,topics[i].nick,BGTABLE,topics[i].topic);
291   printf("</table>\n<br><br>\n\n");
292   
293   /* random urls */
294   printf("<font color=\"%s\"><h3>%s</h3></font>\n",TITLE2,RANDURLS);
295   printf("<table>\n<tr><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">%s</td></tr>\n",BGTITLE,POSTEDBY,BGTITLE,POSTEDURL);
296   for (i=4;i>=0;i--)
297     printf("<tr><td bgcolor=\"%s\">%s</td><td bgcolor=\"%s\">\"<a href=\"%s\">%s</a>\"</td></tr>\n",BGTABLE,urls[i].nick,BGTABLE,urls[i].url,urls[i].url);
298   printf("</table>\n<br><br>\n\n");
299   
300   /* big numbers (todo...)
301   printf("<font color=\"%s\"><h3>%s</h3></font>\n",TITLE2,BIGNUMBERS);
302   */
303   
304   /* footer */
305   printf(TIME,totallines,(int)(time(NULL)-debut));
306   printf("<br>\n%s <a href=\"%s\">irssistats %s</a>",FOOTER,URL,VERSION);
307   printf("\n\n</center>\n\n</body>\n\n</html>\n");
308   
309   return(0);
310 }