Fixed Bignumbers Plugin
[onis.git] / lib / Onis / Plugins / Bignumbers.pm
1 package Onis::Plugins::Bignumbers;
2
3 use strict;
4 use warnings;
5
6 use Exporter;
7
8 use Onis::Html (qw(get_filehandle));
9 use Onis::Language (qw(translate));
10 use Onis::Data::Core (qw(get_main_nick register_plugin nick_to_name));
11 use Onis::Data::Persistent ();
12 use Onis::Plugins::Core (qw(get_core_nick_counters));
13
14 @Onis::Plugins::Bignumbers::EXPORT_OK = (qw(get_bignumbers));
15 @Onis::Plugins::Bignumbers::ISA = ('Exporter');
16
17 our $BigNumbers = Onis::Data::Persistent->new ('BigNumbers', 'nick', qw(questions uppercase smiley_happy smiley_sad));
18 our $CalcData = {};
19
20 register_plugin ('TEXT', \&add);
21 register_plugin ('ACTION', \&add);
22 register_plugin ('OUTPUT', \&output);
23
24 my $VERSION = '$Id$';
25 print STDERR $/, __FILE__, ": $VERSION" if ($::DEBUG);
26
27 return (1);
28
29 sub add
30 {
31         my $data = shift;
32
33         my $nick = $data->{'nick'};
34         my $text = $data->{'text'};
35
36         my $mod = 0;
37
38         my @nums = $BigNumbers->get ($nick);
39         if (!@nums)
40         {
41                 @nums = (0, 0, 0, 0);
42                 $mod++;
43         }
44
45         if ($text =~ m/\b\?/)
46         {
47                 $nums[0]++;
48                 $mod++;
49         }
50
51         if ((uc ($text) eq $text) and ($text =~ m/[A-Z]/))
52         {
53                 $nums[1]++;
54                 $mod++;
55         }
56
57         if ($text =~ m/( |^)[;:]-?\)( |$)/)
58         {
59                 $nums[2]++;
60                 $mod++;
61         }
62
63         if ($text =~ m/( |^):-?\(( |$)/)
64         {
65                 $nums[3]++;
66                 $mod++;
67         }
68
69         if ($mod)
70         {
71                 $BigNumbers->put ($nick, @nums);
72         }
73
74         return (1);
75 }
76
77 sub calculate
78 {
79         for ($BigNumbers->keys ())
80         {
81                 my $nick = $_;
82                 my $main = get_main_nick ($nick);
83                 my ($questions, $uppercase, $smiley_happy, $smiley_sad) = $BigNumbers->get ($nick);
84
85                 next unless (defined ($smiley_sad));
86                 
87                 if (!defined ($CalcData->{$main}))
88                 {
89                         my $core_data = get_core_nick_counters ($main);
90                         next unless (%$core_data);
91
92                         $CalcData->{$main} =
93                         {
94                                 lines => $core_data->{'lines_total'},
95                                 words => $core_data->{'words_total'},
96                                 chars => $core_data->{'chars_total'},
97                                 questions    => 0,
98                                 uppercase    => 0,
99                                 smiley_happy => 0,
100                                 smiley_sad   => 0
101                         };
102                 }
103
104                 $CalcData->{$main}{'questions'}    += $questions;
105                 $CalcData->{$main}{'uppercase'}    += $uppercase;
106                 $CalcData->{$main}{'smiley_happy'} += $smiley_happy;
107                 $CalcData->{$main}{'smiley_sad'}   += $smiley_sad;
108         }
109 }
110
111 sub output
112 {
113         calculate ();
114
115         my $first_nick;
116         my $first_name;
117         my $second_nick;
118         my $second_name;
119         my $trans;
120
121         my $fh = get_filehandle ();
122         
123         $trans = translate ('Big Numbers');
124         print $fh <<EOF;
125 <table class="plugin bignumbers">
126   <tr>
127     <th>$trans</th>
128   </tr>
129 EOF
130         ($first_nick, $second_nick) = sort_by_field ('questions');
131         if ($first_nick)
132         {
133                 my $percent = 100 * $CalcData->{$first_nick}{'questions'} / $CalcData->{$first_nick}{'lines'};
134                 my $trans = translate ('questions0: %s %2.1f%%');
135                 $first_name = nick_to_name ($first_nick) || $first_nick;
136
137                 print $fh "  <tr>\n    <td>";
138                 printf $fh ($trans, $first_name, $percent);
139                 
140                 if ($second_nick)
141                 {
142                         $percent = 100 * $CalcData->{$second_nick}{'questions'} / $CalcData->{$second_nick}{'lines'};
143                         $trans = translate ('questions1: %s %2.1f%%');
144                         $second_name = nick_to_name ($second_nick) || $second_nick;
145
146                         print $fh "<br />\n",
147                         qq#      <span class="small">#;
148                         printf $fh ($trans, $second_name, $percent);
149                         print $fh '</span>';
150                 }
151                 
152                 print $fh "</td>\n  </tr>\n";
153         }
154
155         ($first_nick, $second_nick) = sort_by_field ('uppercase');
156         if ($first_nick)
157         {
158                 my $percent = 100 * $CalcData->{$first_nick}{'uppercase'} / $CalcData->{$first_nick}{'lines'};
159                 my $trans = translate ('yells0: %s %2.1f%%');
160                 $first_name = nick_to_name ($first_nick) || $first_nick;
161
162                 print $fh "  <tr>\n    <td>";
163                 printf $fh ($trans, $first_name, $percent);
164
165                 if ($second_nick)
166                 {
167                         $percent = 100 * $CalcData->{$second_nick}{'uppercase'} / $CalcData->{$second_nick}{'lines'};
168                         $trans = translate ('yells1: %s %2.1f%%');
169                         $second_name = nick_to_name ($second_nick) || $second_nick;
170
171                         print $fh "<br />\n",
172                         qq#      <span class="small">#;
173                         printf $fh ($trans, $second_name, $percent);
174                         print $fh "</span>";
175                 }
176
177                 print $fh "</td>\n  </tr>\n";
178         }
179
180         ($first_nick, $second_nick) = sort_by_field ('smiley_happy');
181         if ($first_nick)
182         {
183                 my $percent = 100 * $CalcData->{$first_nick}{'smiley_happy'} / $CalcData->{$first_nick}{'lines'};
184                 my $trans = translate ('happy0: %s %2.1f%%');
185                 $first_name = nick_to_name ($first_nick) || $first_nick;
186
187                 print $fh "  <tr>\n    <td>";
188                 printf $fh ($trans, $first_name, $percent);
189                 
190                 if ($second_nick)
191                 {
192                         $percent = 100 * $CalcData->{$second_nick}{'smiley_happy'} / $CalcData->{$second_nick}{'lines'};
193                         $trans = translate ('happy1: %s %2.1f%%');
194                         $second_name = nick_to_name ($second_nick) || $second_nick;
195
196                         print $fh "<br />\n",
197                         qq#      <span class="small">#;
198                         printf $fh ($trans, $second_name, $percent);
199                         print $fh "</span>";
200                 }
201                 
202                 print $fh "</td>\n  </tr>\n";
203         }
204
205         ($first_nick, $second_nick) = sort_by_field ('smiley_sad');
206         if ($first_nick)
207         {
208                 my $percent = 100 * $CalcData->{$first_nick}{'smiley_sad'} / $CalcData->{$first_nick}{'lines'};
209                 my $trans = translate ('sad0: %s %2.1f%%');
210                 $first_name = nick_to_name ($first_nick) || $first_nick;
211
212                 print $fh "  <tr>\n    <td>";
213                 printf $fh ($trans, $first_name, $percent);
214                 
215                 if ($second_nick)
216                 {
217                         $percent = 100 * $CalcData->{$second_nick}{'smiley_sad'} / $CalcData->{$second_nick}{'lines'};
218                         $trans = translate ('sad1: %s %2.1f%%');
219                         $second_name = nick_to_name ($second_nick) || $second_nick;
220
221                         print $fh "<br />\n",
222                         qq#      <span class="small">#;
223                         printf $fh ($trans, $second_name, $percent);
224                         print $fh "</span>";
225                 }
226                 
227                 print $fh "</td>\n  </tr>\n";
228         }
229
230         {
231                 my @names = sort_by_field ('chars');
232                 
233                 my $longest = '';
234                 my $longest2 = '';
235                 my $shortest = '';
236                 my $shortest2 = '';
237                 
238                 my $chan_chars = 0;
239                 my $chan_lines = 0;
240                 
241                 for (@names)
242                 {
243                         $chan_chars += $CalcData->{$_}{'chars'} || 0;
244                         $chan_lines += $CalcData->{$_}{'lines'} || 0;
245                 }
246
247                 if (@names)
248                 {
249                         $longest = shift (@names);
250                 }
251                 if (@names)
252                 {
253                         $longest2 = shift (@names);
254                 }
255                 if (@names)
256                 {
257                         $shortest = pop (@names);
258                 }
259                 if (@names)
260                 {
261                         $shortest2 = pop (@names);
262                 }
263                 
264                 if ($longest)
265                 {
266                         my $avg = $CalcData->{$longest}{'chars'} / $CalcData->{$longest}{'lines'};
267                         my $trans = translate ('max chars0: %s %1.1f');
268                         $first_name = nick_to_name ($longest) || $longest;
269                         
270                         print $fh "  <tr>\n    <td>";
271                         printf $fh ($trans, $first_name, $avg);
272                         
273                         if ($longest2)
274                         {
275                                 $avg = $CalcData->{$longest2}{'chars'} / $CalcData->{$longest2}{'lines'};
276                                 $trans = translate ('max chars1: %s %1.1f');
277                                 $second_name = nick_to_name ($longest2) || $longest2;
278
279                                 print $fh "<br />\n",
280                                 qq#      <span class="small">#;
281                                 printf $fh ($trans, $second_name, $avg);
282                                 print $fh "</span>";
283                         }
284
285                         $avg = $chan_chars / $chan_lines;
286                         $trans = translate ('chars avg: %1.1f');
287
288                         print $fh "<br />\n",
289                         qq#      <span class="small">#;
290                         printf $fh ($trans, $avg);
291                         print $fh "</span></td>\n  </tr>\n";
292                 }
293
294                 if ($shortest)
295                 {
296                         my $avg = $CalcData->{$shortest}{'chars'} / $CalcData->{$shortest}{'lines'};
297                         my $trans = translate ('min chars0: %s %1.1f');
298                         $first_name = nick_to_name ($shortest) || $shortest;
299                         
300                         print $fh "  <tr>\n    <td>";
301                         printf $fh ($trans, $first_name, $avg);
302                         
303                         if ($shortest2)
304                         {
305                                 $avg = $CalcData->{$shortest2}{'chars'} / $CalcData->{$shortest2}{'lines'};
306                                 $trans = translate ('min chars1: %s %1.1f');
307                                 $second_name = nick_to_name ($shortest2) || $shortest2;
308
309                                 print $fh "<br />\n",
310                                 qq#      <span class="small">#;
311                                 printf $fh ($trans, $second_name, $avg);
312                                 print $fh "</span>";
313                         }
314                         print $fh "</td>\n  </tr>\n";
315                 }
316         }
317         
318         {
319                 my @names = sort_by_field ('words');
320
321                 $first_nick = '';
322                 $second_nick = '';
323
324                 my $chan_words = 0;
325                 my $chan_lines = 0;
326                 
327                 for (@names)
328                 {
329                         $chan_words += $CalcData->{$_}{'words'} || 0;
330                         $chan_lines += $CalcData->{$_}{'lines'} || 0;
331                 }
332                 
333                 if (@names)
334                 {
335                         $first_nick = shift (@names);
336                 }
337                 if (@names)
338                 {
339                         $second_nick = shift (@names);
340                 }
341
342                 if ($first_nick)
343                 {
344                         my $avg = $CalcData->{$first_nick}{'words'} / $CalcData->{$first_nick}{'lines'};
345                         my $trans = translate ('max words0: %s %1.1f');
346                         $first_name = nick_to_name ($first_nick) || $first_nick;
347                         
348                         print $fh "  <tr>\n    <td>";
349                         printf $fh ($trans, $first_name, $avg);
350
351                         if ($second_nick)
352                         {
353                                 $avg = $CalcData->{$second_nick}{'words'} / $CalcData->{$second_nick}{'lines'};
354                                 $trans = translate ('max words1: %s %1.1f');
355                                 $second_name = nick_to_name ($second_nick) || $second_nick;
356
357                                 print $fh "<br />\n",
358                                 qq#      <span class="small">#;
359                                 printf $fh ($trans, $second_name, $avg);
360                                 print $fh "</span>";
361                         }
362
363                         $avg = $chan_words / $chan_lines;
364                         $trans = translate ('words avg: %1.1f');
365                         
366                         print $fh "<br />\n",
367                         qq#      <span class="small">#;
368                         printf $fh ($trans, $avg);
369                         print $fh "</span></td>\n  </tr>\n";
370                 }
371         }
372
373         print $fh "</table>\n\n";
374 }
375
376 sub sort_by_field
377 {
378         my $field = shift;
379
380         my @retval = sort
381         {
382                 ($CalcData->{$b}{$field} / $CalcData->{$b}{'lines'})
383                 <=>
384                 ($CalcData->{$a}{$field} / $CalcData->{$a}{'lines'})
385         } grep
386         {
387                 defined ($CalcData->{$_}{'lines'})
388                         and ($CalcData->{$_}{'lines'} != 0)
389                         and defined ($CalcData->{$_}{$field})
390         }
391         (keys (%$CalcData));
392         
393         while (scalar (@retval) < 2)
394         {
395                 push (@retval, '');
396         }
397
398         return (@retval);
399 }
400
401 sub get_bignumbers
402 {
403         my $nick = shift;
404
405         if (!defined ($CalcData->{$nick}))
406         {
407                 return ({});
408         }
409
410         return ($CalcData->{$nick});
411 }