1 package Onis::Plugins::Core;
12 Plugin for the main table and the hourly-statistics. This is the most
13 complicated plugin so far.
17 use Onis::Config qw/get_config/;
18 use Onis::Html qw/html_escape get_filehandle/;
19 use Onis::Language qw/translate/;
20 use Onis::Users qw/get_name get_link get_image nick_to_username/;
21 use Onis::Data::Core qw#get_all_nicks nick_to_ident ident_to_nick get_main_nick register_plugin#;
22 use Onis::Data::Persistent;
24 our $NickLinesCounter = Onis::Data::Persistent->new ('NickLinesCounter', 'nick',
26 lines00 lines01 lines02 lines03 lines04 lines05 lines06 lines07 lines08 lines09 lines10 lines11
27 lines12 lines13 lines14 lines15 lines16 lines17 lines18 lines19 lines20 lines21 lines22 lines23
30 our $NickWordsCounter = Onis::Data::Persistent->new ('NickWordsCounter', 'nick',
32 words00 words01 words02 words03 words04 words05 words06 words07 words08 words09 words10 words11
33 words12 words13 words14 words15 words16 words17 words18 words19 words20 words21 words22 words23
36 our $NickCharsCounter = Onis::Data::Persistent->new ('NickCharsCounter', 'nick',
38 chars00 chars01 chars02 chars03 chars04 chars05 chars06 chars07 chars08 chars09 chars10 chars11
39 chars12 chars13 chars14 chars15 chars16 chars17 chars18 chars19 chars20 chars21 chars22 chars23
43 our $QuoteCache = {}; # Saves per-nick information without any modification
44 our $QuoteData = {}; # Is generated before output. Nicks are merged according to Data::Core.
46 our @H_IMAGES = qw#dark-theme/h-red.png dark-theme/h-blue.png dark-theme/h-yellow.png dark-theme/h-green.png#;
47 our $QuoteCache_SIZE = 10;
51 our $SORT_BY = 'LINES';
52 our $DISPLAY_LINES = 'BOTH';
53 our $DISPLAY_WORDS = 'NONE';
54 our $DISPLAY_CHARS = 'NONE';
55 our $DISPLAY_TIMES = 0;
56 our $DISPLAY_IMAGES = 0;
57 our $DEFAULT_IMAGE = '';
58 our $BAR_HEIGHT = 130;
63 if (get_config ('quote_cache_size'))
65 my $tmp = get_config ('quote_cache_size');
67 $QuoteCache_SIZE = $tmp if ($tmp);
69 if (get_config ('quote_min'))
71 my $tmp = get_config ('quote_min');
73 $QuoteMin = $tmp if ($tmp);
75 if (get_config ('quote_max'))
77 my $tmp = get_config ('quote_max');
79 $QuoteMax = $tmp if ($tmp);
81 if (get_config ('min_word_length'))
83 my $tmp = get_config ('min_word_length');
85 $WORD_LENGTH = $tmp if ($tmp);
87 if (get_config ('display_lines'))
89 my $tmp = get_config ('display_lines');
92 if (($tmp eq 'NONE') or ($tmp eq 'BAR') or ($tmp eq 'NUMBER') or ($tmp eq 'BOTH'))
94 $DISPLAY_LINES = $tmp;
98 $tmp = get_config ('display_lines');
99 print STDERR $/, __FILE__, ": ``display_lines'' has been set to the invalid value ``$tmp''. ",
100 $/, __FILE__, ": Valid values are ``none'', ``bar'', ``number'' and ``both''. Using default value ``both''.";
103 if (get_config ('display_words'))
105 my $tmp = get_config ('display_words');
108 if (($tmp eq 'NONE') or ($tmp eq 'BAR') or ($tmp eq 'NUMBER') or ($tmp eq 'BOTH'))
110 $DISPLAY_WORDS = $tmp;
114 $tmp = get_config ('display_words');
115 print STDERR $/, __FILE__, ": ``display_words'' has been set to the invalid value ``$tmp''. ",
116 $/, __FILE__, ": Valid values are ``none'', ``bar'', ``number'' and ``both''. Using default value ``none''.";
119 if (get_config ('display_chars'))
121 my $tmp = get_config ('display_chars');
124 if (($tmp eq 'NONE') or ($tmp eq 'BAR') or ($tmp eq 'NUMBER') or ($tmp eq 'BOTH'))
126 $DISPLAY_CHARS = $tmp;
130 $tmp = get_config ('display_chars');
131 print STDERR $/, __FILE__, ": ``display_chars'' has been set to the invalid value ``$tmp''. ",
132 $/, __FILE__, ": Valid values are ``none'', ``bar'', ``number'' and ``both''. Using default value ``none''.";
135 if (get_config ('display_times'))
137 my $tmp = get_config ('display_times');
139 if ($tmp =~ m/true|on|yes/i)
143 elsif ($tmp =~ m/false|off|no/i)
149 print STDERR $/, __FILE__, ": ``display_times'' has been set to the invalid value ``$tmp''. ",
150 $/, __FILE__, ": Valid values are ``true'' and ``false''. Using default value ``false''.";
153 if (get_config ('display_images'))
155 my $tmp = get_config ('display_images');
157 if ($tmp =~ m/true|on|yes/i)
161 elsif ($tmp =~ m/false|off|no/i)
167 print STDERR $/, __FILE__, ": ``display_times'' has been set to the invalid value ``$tmp''. ",
168 $/, __FILE__, ": Valid values are ``true'' and ``false''. Using default value ``false''.";
171 if (get_config ('default_image'))
173 $DEFAULT_IMAGE = get_config ('default_image');
175 if (get_config ('sort_by'))
177 my $tmp = get_config ('sort_by');
180 if (($tmp eq 'LINES') or ($tmp eq 'WORDS') or ($tmp eq 'CHARS'))
186 $tmp = get_config ('sort_by');
187 print STDERR $/, __FILE__, ": ``sort_by'' has been set to the invalid value ``$tmp''. ",
188 $/, __FILE__, ": Valid values are ``lines'' and ``words''. Using default value ``lines''.";
191 if (get_config ('horizontal_images'))
193 my @tmp = get_config ('horizontal_images');
196 if (scalar (@tmp) != 4)
198 print STDERR $/, __FILE__, ": The number of horizontal images is not four. The output might look weird.", $/;
201 for ($i = 0; $i < 4; $i++)
203 if (!defined ($tmp[$i]))
208 $H_IMAGES[$i] = $tmp[$i];
211 if (get_config ('bar_height'))
213 my $tmp = get_config ('bar_height');
215 $BAR_HEIGHT = $tmp if ($tmp >= 10);
217 if (get_config ('bar_width'))
219 my $tmp = get_config ('bar_width');
221 $BAR_WIDTH = $tmp if ($tmp >= 10);
223 if (get_config ('longlines'))
225 my $tmp = get_config ('longlines');
227 $LONGLINES = $tmp if ($tmp);
229 if (get_config ('shortlines'))
231 my $tmp = get_config ('shortlines');
233 if ($tmp or ($tmp == 0))
239 register_plugin ('TEXT', \&add);
240 register_plugin ('ACTION', \&add);
241 register_plugin ('OUTPUT', \&output);
243 my $VERSION = '$Id$';
244 print STDERR $/, __FILE__, ": $VERSION" if ($::DEBUG);
252 my $nick = $data->{'nick'};
253 my $ident = $data->{'ident'};
254 my $hour = int ($data->{'hour'});
255 my $host = $data->{'host'};
256 my $text = $data->{'text'};
257 my $type = $data->{'type'};
258 my $time = $data->{'epoch'};
260 my $words = scalar (@{$data->{'words'}});
261 my $chars = length ($text);
263 if ($type eq 'ACTION')
265 $chars -= (length ($nick) + 3);
268 my @counter = $NickLinesCounter->get ($nick);
271 @counter = qw(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0);
274 $NickLinesCounter->put ($nick, @counter);
276 @counter = $NickWordsCounter->get ($nick);
279 @counter = qw(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0);
281 $counter[$hour] += $words;
282 $NickWordsCounter->put ($nick, @counter);
284 @counter = $NickCharsCounter->get ($nick);
287 @counter = qw(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0);
289 $counter[$hour] += $chars;
290 $NickCharsCounter->put ($nick, @counter);
292 if ((length ($text) >= $QuoteMin)
293 and (length ($text) <= $QuoteMax))
295 if (!defined ($QuoteCache->{$nick}))
297 $QuoteCache->{$nick} = [];
299 push (@{$QuoteCache->{$nick}}, [$time, $text]);
302 if (defined ($QuoteCache->{$nick}))
304 while (scalar (@{$QuoteCache->{$nick}}) > $QuoteCache_SIZE)
306 shift (@{$QuoteCache->{$nick}});
315 for (get_all_nicks ())
318 my $main = get_main_nick ($nick);
320 if (!defined ($NickData->{$main}))
324 lines => [qw(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)],
325 words => [qw(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)],
326 chars => [qw(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)]
330 my @counter = $NickLinesCounter->get ($nick);
333 for (my $i = 0; $i < 24; $i++)
335 $NickData->{$main}{'lines'}[$i] += $counter[$i];
339 @counter = $NickWordsCounter->get ($nick);
342 for (my $i = 0; $i < 24; $i++)
344 $NickData->{$main}{'words'}[$i] += $counter[$i];
348 @counter = $NickWordsCounter->get ($nick);
351 for (my $i = 0; $i < 24; $i++)
353 $NickData->{$main}{'words'}[$i] += $counter[$i];
357 if (!defined ($QuoteData->{$main}))
359 $QuoteData->{$main} = [];
361 if (defined ($QuoteCache->{$nick}))
363 my @new = sort (sub { $b->[0] <=> $a->[0] }, @{$QuoteCache->{$nick}}, @{$QuoteData->{$main}});
364 splice (@new, $QuoteCache_SIZE) if (scalar (@new) > $QuoteCache_SIZE);
365 $QuoteData->{$main} = \@new;
379 my $max = 0; # the most lines that were written in one hour..
380 my $total = 0; # the total amount of lines we wrote..
381 my ($i, $j); # used in for-loops
382 my $factor = 0; # used to find a bar's height
383 my $newline = ''; # buffer variable..
385 my @data = @{$DATA->{'byhour'}};
387 my @img_urls = get_config ('vertical_images');
390 @img_urls = qw#images/ver0n.png images/ver1n.png images/ver2n.png images/ver3n.png#;
393 my $fh = get_filehandle () or die;
395 # this for loop looks for the most amount of lines in one hour and sets
397 for ($i = 0; $i < 24; $i++)
399 if (!defined ($data[$i]))
406 if ($data[$i] > $max)
418 $factor = (($BAR_HEIGHT - 1) / $max);
420 my $header = translate ('When do we actually talk here?');
421 print $fh "<h2>$header</h2>\n",
422 qq#<table class="hours_of_day">\n#,
425 # this for circles through the four colors. Each color represents six hours.
426 # (4 * 6 hours = 24 hours)
427 for ($i = 0; $i <= 3; $i++)
429 for ($j = 0; $j <= 5; $j++)
431 my $hour = (($i * 6) + $j);
432 if (!defined ($data[$hour]))
437 my $percent = 100 * ($data[$hour] / $total);
438 my $height = int ($data[$hour] * $factor) + 1;
439 my $img_url = $img_urls[$i];
441 print $fh ' <td>', sprintf ("%2.1f", $percent),
442 qq#%<br /><img src="$img_url" style="height: $height#,
443 qq#px;" alt="" /></td>\n#;
447 print $fh " </tr>\n",
448 qq# <tr class="hour_row">\n#;
449 print $fh map { " <td>$_</td>\n" } (0 .. 23);
450 print $fh " </tr>\n",
460 defined ($DATA->{'byname'}{$_}{'words'})
461 } (keys (%{$DATA->{'byname'}}));
469 my $fh = get_filehandle () or die;
471 my $sort_field = lc ($SORT_BY);
476 ($tmp) = sort { $DATA->{'byname'}{$b}{'lines'} <=> $DATA->{'byname'}{$a}{'lines'} } (@names);
477 $max_lines = $DATA->{'byname'}{$tmp}{'lines'} || 0;
479 ($tmp) = sort { $DATA->{'byname'}{$b}{'words'} <=> $DATA->{'byname'}{$a}{'words'} } (@names);
480 $max_words = $DATA->{'byname'}{$tmp}{'words'} || 0;
482 ($tmp) = sort { $DATA->{'byname'}{$b}{'chars'} <=> $DATA->{'byname'}{$a}{'chars'} } (@names);
483 $max_chars = $DATA->{'byname'}{$tmp}{'chars'} || 0;
485 $trans = translate ('Most active nicks');
487 print $fh "<h2>$trans</h2>\n";
488 if ($SORT_BY eq 'LINES')
490 $trans = translate ('Nicks sorted by numbers of lines written');
492 elsif ($SORT_BY eq 'WORDS')
494 $trans = translate ('Nicks sorted by numbers of words written');
496 else # ($SORT_BY eq 'CHARS')
498 $trans = translate ('Nicks sorted by numbers of characters written');
500 print $fh "<p>($trans)</p>\n";
504 <table class="big_ranking">
506 <td class="invis"> </td>
510 $trans = translate ('Image');
511 print $fh " <th>$trans</th>\n";
515 $trans = translate ('Nick');
516 print $fh " <th>$trans</th>\n";
518 if ($DISPLAY_LINES ne 'NONE')
520 $trans = translate ('Number of Lines');
521 print $fh " <th>$trans</th>\n";
523 if ($DISPLAY_WORDS ne 'NONE')
525 $trans = translate ('Number of Words');
526 print $fh " <th>$trans</th>\n";
528 if ($DISPLAY_CHARS ne 'NONE')
530 $trans = translate ('Number of Characters');
531 print $fh " <th>$trans</th>\n";
535 $trans = translate ('When?');
536 print $fh " <th>$trans</th>\n";
539 $trans = translate ('Random Quote');
540 print $fh " <th>$trans</th>\n",
545 $DATA->{'byname'}{$b}{$sort_field} <=> $DATA->{'byname'}{$a}{$sort_field}
552 if (ident_to_nick ($name))
554 $nick = ident_to_nick ($name);
558 $ident = nick_to_ident ($name);
563 # As long as we didn't hit the
564 # $LONGLINES-limit we continue
566 if ($linescount <= $LONGLINES)
568 my $quote = translate ('-- no quote available --');
570 if (defined ($QuoteCache->{$nick}))
572 my $num = scalar (@{$QuoteCache->{$nick}});
573 my $rand = int (rand ($num));
574 $quote = html_escape ($QuoteCache->{$nick}[$rand]);
582 $link = get_link ($name);
583 $image = get_image ($name);
584 $title = get_name ($name);
588 qq# <td class="numeration"># . $linescount . "</td>\n";
592 if ($DEFAULT_IMAGE and !$image)
594 $image = $DEFAULT_IMAGE;
597 print $fh qq# <td class="image">#;
602 print $fh qq#<a href="$link">#;
604 print $fh qq#<img src="$image" alt="$name" />#;
619 $title = "Ident: $ident";
621 print $fh qq# <td class="nick" title="$title">#;
625 print $fh qq#<a href="$link">$name</a></td>\n#
629 print $fh qq#$name</td>\n#;
632 if ($DISPLAY_LINES ne 'NONE')
634 print $fh qq# <td class="bar">#;
635 if (($DISPLAY_LINES eq 'BOTH') or ($DISPLAY_LINES eq 'BAR'))
637 my $code = bar ($max_lines, $DATA->{'byname'}{$name}{'lines_time'});
640 print $fh ' ' if ($DISPLAY_LINES eq 'BOTH');
641 if (($DISPLAY_LINES eq 'BOTH') or ($DISPLAY_LINES eq 'NUMBER'))
643 print $fh $DATA->{'byname'}{$name}{'lines'};
648 if ($DISPLAY_WORDS ne 'NONE')
650 print $fh qq# <td class="bar">#;
651 if (($DISPLAY_WORDS eq 'BOTH') or ($DISPLAY_WORDS eq 'BAR'))
653 my $code = bar ($max_words, $DATA->{'byname'}{$name}{'words_time'});
656 print $fh ' ' if ($DISPLAY_WORDS eq 'BOTH');
657 if (($DISPLAY_WORDS eq 'BOTH') or ($DISPLAY_WORDS eq 'NUMBER'))
659 print $fh $DATA->{'byname'}{$name}{'words'};
664 if ($DISPLAY_CHARS ne 'NONE')
666 print $fh qq# <td class="bar">#;
667 if (($DISPLAY_CHARS eq 'BOTH') or ($DISPLAY_CHARS eq 'BAR'))
669 my $code = bar ($max_chars, $DATA->{'byname'}{$name}{'chars_time'});
672 print $fh ' ' if ($DISPLAY_CHARS eq 'BOTH');
673 if (($DISPLAY_CHARS eq 'BOTH') or ($DISPLAY_CHARS eq 'NUMBER'))
675 print $fh $DATA->{'byname'}{$name}{'chars'};
682 my $chars = $DATA->{'byname'}{$name}{'chars'};
683 my $code = bar ($chars, $DATA->{'byname'}{$name}{'chars_time'});
685 print $fh qq# <td class="bar">$code</td>\n#;
688 print $fh qq# <td class="quote">$quote</td>\n#,
691 if ($linescount == $LONGLINES)
693 print $fh "</table>\n\n";
697 # Ok, we have too many people to
698 # list them all so we start a
699 # smaller table and just list the
700 # names.. (Six names per line..)
701 elsif ($linescount <= ($LONGLINES + 6 * $SHORTLINES))
703 my $row_in_this_table = int (($linescount - $LONGLINES - 1) / 6);
704 my $col_in_this_table = ($linescount - $LONGLINES - 1) % 6;
707 if ($SORT_BY eq 'LINES')
709 $total = $DATA->{'byname'}{$name}{'lines'};
711 elsif ($SORT_BY eq 'WORDS')
713 $total = $DATA->{'byname'}{$name}{'words'};
715 else # ($SORT_BY eq 'CHARS')
717 $total = $DATA->{'byname'}{$name}{'chars'};
720 if ($row_in_this_table == 0 and $col_in_this_table == 0)
722 $trans = translate ("They didn't write so much");
723 print $fh "<h2>$trans</h2>\n",
724 qq#<table class="small_ranking">\n#,
728 if ($col_in_this_table == 0 and $row_in_this_table != 0)
730 print $fh " </tr>\n",
734 print $fh " <td>$name ($total)</td>\n";
736 if ($row_in_this_table == $SHORTLINES and $col_in_this_table == 5)
738 print $fh " </tr>\n",
743 # There is no else. There are
744 # just too many people around.
745 # I might add a "There are xyz
746 # unmentioned nicks"-line..
749 if (($linescount > $LONGLINES)
750 and ($linescount <= ($LONGLINES + 6 * $SHORTLINES)))
752 my $col = ($linescount - $LONGLINES - 1) % 6;
756 print $fh qq# <td> </td>\n#;
760 print $fh " </tr>\n";
763 if ($linescount != $LONGLINES)
765 print $fh "</table>\n\n";
769 # this is called by "&ranking ();" and prints the horizontal usage-bar in the
770 # detailed nick-table
777 # BAR_WIDTH is a least 10
778 my $max_width = $BAR_WIDTH - 4;
785 if (!$max_num) { return ($retval); }
786 $factor = $max_width / $max_num;
788 for ($i = 0; $i < 4; $i++)
792 my $img = $H_IMAGES[$i];
794 for ($j = 0; $j < 6; $j++)
796 my $hour = ($i * 6) + $j;
798 if (defined ($source->{$hour}))
800 $sum += $source->{$hour};
804 $width += int (0.5 + ($sum * $factor));
806 $retval .= qq#<img src="$img" style="width: # . $width . q#px"#;
807 if ($i == 0) { $retval .= qq# class="first"#; }
808 elsif ($i == 3) { $retval .= qq# class="last"#; }
809 $retval .= ' alt="" />';
817 Florian octo Forster, E<lt>octo at verplant.orgE<gt>