e24a8a6c5d594b192c468c44205a41a5358f5a1f
[onis.git] / lib / Onis / Plugins / Core.pm
1 package Onis::Plugins::Core;
2
3 use strict;
4 use warnings;
5
6 use Carp (qw(confess));
7
8 =head1 NAME
9
10 Onis::Plugins::Core
11
12 =head1 DESCRIPTION
13
14 Plugin for the main table and the hourly-statistics. This is the most
15 complicated plugin so far.
16
17 =cut
18
19 use Onis::Config qw/get_config/;
20 use Onis::Html qw/html_escape get_filehandle/;
21 use Onis::Language qw/translate/;
22 use Onis::Users (qw(get_realname get_link get_image ident_to_name));
23 use Onis::Data::Core qw#get_all_nicks nick_to_ident ident_to_nick get_main_nick register_plugin#;
24 use Onis::Data::Persistent;
25
26 our $NickLinesCounter = Onis::Data::Persistent->new ('NickLinesCounter', 'nick',
27         qw(
28                 lines00 lines01 lines02 lines03 lines04 lines05 lines06 lines07 lines08 lines09 lines10 lines11
29                 lines12 lines13 lines14 lines15 lines16 lines17 lines18 lines19 lines20 lines21 lines22 lines23
30         )
31 );
32 our $NickWordsCounter = Onis::Data::Persistent->new ('NickWordsCounter', 'nick',
33         qw(
34                 words00 words01 words02 words03 words04 words05 words06 words07 words08 words09 words10 words11
35                 words12 words13 words14 words15 words16 words17 words18 words19 words20 words21 words22 words23
36         )
37 );
38 our $NickCharsCounter = Onis::Data::Persistent->new ('NickCharsCounter', 'nick',
39         qw(
40                 chars00 chars01 chars02 chars03 chars04 chars05 chars06 chars07 chars08 chars09 chars10 chars11
41                 chars12 chars13 chars14 chars15 chars16 chars17 chars18 chars19 chars20 chars21 chars22 chars23
42         )
43 );
44
45 our $QuoteCache = {}; # Saves per-nick information without any modification
46 our $QuoteData = {};  # Is generated before output. Nicks are merged according to Data::Core.
47 our $NickData = {}:  # Same as above, but for nicks rather than quotes.
48
49 our @H_IMAGES = qw#dark-theme/h-red.png dark-theme/h-blue.png dark-theme/h-yellow.png dark-theme/h-green.png#;
50 our $QuoteCacheSize = 10;
51 our $QuoteMin = 30;
52 our $QuoteMax = 80;
53 our $WORD_LENGTH = 5;
54 our $SORT_BY = 'LINES';
55 our $DISPLAY_LINES = 'BOTH';
56 our $DISPLAY_WORDS = 'NONE';
57 our $DISPLAY_CHARS = 'NONE';
58 our $DISPLAY_TIMES = 0;
59 our $DISPLAY_IMAGES = 0;
60 our $DEFAULT_IMAGE = '';
61 our $BAR_HEIGHT = 130;
62 our $BAR_WIDTH  = 100;
63 our $LongLines  = 50;
64 our $ShortLines = 10;
65
66 if (get_config ('quote_cache_size'))
67 {
68         my $tmp = get_config ('quote_cache_size');
69         $tmp =~ s/\D//g;
70         $QuoteCacheSize = $tmp if ($tmp);
71 }
72 if (get_config ('quote_min'))
73 {
74         my $tmp = get_config ('quote_min');
75         $tmp =~ s/\D//g;
76         $QuoteMin = $tmp if ($tmp);
77 }
78 if (get_config ('quote_max'))
79 {
80         my $tmp = get_config ('quote_max');
81         $tmp =~ s/\D//g;
82         $QuoteMax = $tmp if ($tmp);
83 }
84 if (get_config ('min_word_length'))
85 {
86         my $tmp = get_config ('min_word_length');
87         $tmp =~ s/\D//g;
88         $WORD_LENGTH = $tmp if ($tmp);
89 }
90 if (get_config ('display_lines'))
91 {
92         my $tmp = get_config ('display_lines');
93         $tmp = uc ($tmp);
94
95         if (($tmp eq 'NONE') or ($tmp eq 'BAR') or ($tmp eq 'NUMBER') or ($tmp eq 'BOTH'))
96         {
97                 $DISPLAY_LINES = $tmp;
98         }
99         else
100         {
101                 $tmp = get_config ('display_lines');
102                 print STDERR $/, __FILE__, ": ``display_lines'' has been set to the invalid value ``$tmp''. ",
103                 $/, __FILE__, ": Valid values are ``none'', ``bar'', ``number'' and ``both''. Using default value ``both''.";
104         }
105 }
106 if (get_config ('display_words'))
107 {
108         my $tmp = get_config ('display_words');
109         $tmp = uc ($tmp);
110
111         if (($tmp eq 'NONE') or ($tmp eq 'BAR') or ($tmp eq 'NUMBER') or ($tmp eq 'BOTH'))
112         {
113                 $DISPLAY_WORDS = $tmp;
114         }
115         else
116         {
117                 $tmp = get_config ('display_words');
118                 print STDERR $/, __FILE__, ": ``display_words'' has been set to the invalid value ``$tmp''. ",
119                 $/, __FILE__, ": Valid values are ``none'', ``bar'', ``number'' and ``both''. Using default value ``none''.";
120         }
121 }
122 if (get_config ('display_chars'))
123 {
124         my $tmp = get_config ('display_chars');
125         $tmp = uc ($tmp);
126
127         if (($tmp eq 'NONE') or ($tmp eq 'BAR') or ($tmp eq 'NUMBER') or ($tmp eq 'BOTH'))
128         {
129                 $DISPLAY_CHARS = $tmp;
130         }
131         else
132         {
133                 $tmp = get_config ('display_chars');
134                 print STDERR $/, __FILE__, ": ``display_chars'' has been set to the invalid value ``$tmp''. ",
135                 $/, __FILE__, ": Valid values are ``none'', ``bar'', ``number'' and ``both''. Using default value ``none''.";
136         }
137 }
138 if (get_config ('display_times'))
139 {
140         my $tmp = get_config ('display_times');
141
142         if ($tmp =~ m/true|on|yes/i)
143         {
144                 $DISPLAY_TIMES = 1;
145         }
146         elsif ($tmp =~ m/false|off|no/i)
147         {
148                 $DISPLAY_TIMES = 0;
149         }
150         else
151         {
152                 print STDERR $/, __FILE__, ": ``display_times'' has been set to the invalid value ``$tmp''. ",
153                 $/, __FILE__, ": Valid values are ``true'' and ``false''. Using default value ``false''.";
154         }
155 }
156 if (get_config ('display_images'))
157 {
158         my $tmp = get_config ('display_images');
159
160         if ($tmp =~ m/true|on|yes/i)
161         {
162                 $DISPLAY_IMAGES = 1;
163         }
164         elsif ($tmp =~ m/false|off|no/i)
165         {
166                 $DISPLAY_IMAGES = 0;
167         }
168         else
169         {
170                 print STDERR $/, __FILE__, ": ``display_times'' has been set to the invalid value ``$tmp''. ",
171                 $/, __FILE__, ": Valid values are ``true'' and ``false''. Using default value ``false''.";
172         }
173 }
174 if (get_config ('default_image'))
175 {
176         $DEFAULT_IMAGE = get_config ('default_image');
177 }
178 if (get_config ('sort_by'))
179 {
180         my $tmp = get_config ('sort_by');
181         $tmp = uc ($tmp);
182
183         if (($tmp eq 'LINES') or ($tmp eq 'WORDS') or ($tmp eq 'CHARS'))
184         {
185                 $SORT_BY = $tmp;
186         }
187         else
188         {
189                 $tmp = get_config ('sort_by');
190                 print STDERR $/, __FILE__, ": ``sort_by'' has been set to the invalid value ``$tmp''. ",
191                 $/, __FILE__, ": Valid values are ``lines'' and ``words''. Using default value ``lines''.";
192         }
193 }
194 if (get_config ('horizontal_images'))
195 {
196         my @tmp = get_config ('horizontal_images');
197         my $i;
198         
199         if (scalar (@tmp) != 4)
200         {
201                 print STDERR $/, __FILE__, ": The number of horizontal images is not four. The output might look weird.", $/;
202         }
203
204         for ($i = 0; $i < 4; $i++)
205         {
206                 if (!defined ($tmp[$i]))
207                 {
208                         next;
209                 }
210
211                 $H_IMAGES[$i] = $tmp[$i];
212         }
213 }
214 if (get_config ('bar_height'))
215 {
216         my $tmp = get_config ('bar_height');
217         $tmp =~ s/\D//g;
218         $BAR_HEIGHT = $tmp if ($tmp >= 10);
219 }
220 if (get_config ('bar_width'))
221 {
222         my $tmp = get_config ('bar_width');
223         $tmp =~ s/\D//g;
224         $BAR_WIDTH = $tmp if ($tmp >= 10);
225 }
226 if (get_config ('longlines'))
227 {
228         my $tmp = get_config ('longlines');
229         $tmp =~ s/\D//g;
230         $LongLines = $tmp if ($tmp);
231 }
232 if (get_config ('shortlines'))
233 {
234         my $tmp = get_config ('shortlines');
235         $tmp =~ s/\D//g;
236         if ($tmp or ($tmp == 0))
237         {
238                 $ShortLines = $tmp;
239         }
240 }
241
242 register_plugin ('TEXT', \&add);
243 register_plugin ('ACTION', \&add);
244 register_plugin ('OUTPUT', \&output);
245
246 my $VERSION = '$Id$';
247 print STDERR $/, __FILE__, ": $VERSION" if ($::DEBUG);
248
249 return (1);
250
251 sub add
252 {
253         my $data = shift;
254
255         my $nick = $data->{'nick'};
256         my $ident = $data->{'ident'};
257         my $hour = int ($data->{'hour'});
258         my $host = $data->{'host'};
259         my $text = $data->{'text'};
260         my $type = $data->{'type'};
261         my $time = $data->{'epoch'};
262
263         my $words = scalar (@{$data->{'words'}});
264         my $chars = length ($text);
265
266         if ($type eq 'ACTION')
267         {
268                 $chars -= (length ($nick) + 3);
269         }
270
271         my @counter = $NickLinesCounter->get ($nick);
272         if (!@counter)
273         {
274                 @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);
275         }
276         $counter[$hour]++
277         $NickLinesCounter->put ($nick, @counter);
278
279         @counter = $NickWordsCounter->get ($nick);
280         if (!@counter)
281         {
282                 @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);
283         }
284         $counter[$hour] += $words;
285         $NickWordsCounter->put ($nick, @counter);
286
287         @counter = $NickCharsCounter->get ($nick);
288         if (!@counter)
289         {
290                 @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);
291         }
292         $counter[$hour] += $chars;
293         $NickCharsCounter->put ($nick, @counter);
294
295         if ((length ($text) >= $QuoteMin)
296                                 and (length ($text) <= $QuoteMax))
297         {
298                 if (!defined ($QuoteCache->{$nick}))
299                 {
300                         $QuoteCache->{$nick} = [];
301                 }
302                 push (@{$QuoteCache->{$nick}}, [$time, $text]);
303         }
304
305         if (defined ($QuoteCache->{$nick}))
306         {
307                 while (scalar (@{$QuoteCache->{$nick}}) > $QuoteCacheSize)
308                 {
309                         shift (@{$QuoteCache->{$nick}});
310                 }
311         }
312
313         return (1);
314 }
315
316 sub calculate
317 {
318         for (get_all_nicks ())
319         {
320                 my $nick = $_;
321                 my $main = get_main_nick ($nick);
322
323                 if (!defined ($NickData->{$main}))
324                 {
325                         $NickData->{$main} =
326                         {
327                                 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)],
328                                 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)],
329                                 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                                 lines_total => 0,
331                                 words_total => 0,
332                                 chars_total => 0
333                         };
334                 }
335
336                 my @counter = $NickLinesCounter->get ($nick);
337                 if (@counter)
338                 {
339                         my $sum = 0;
340                         for (my $i = 0; $i < 24; $i++)
341                         {
342                                 $NickData->{$main}{'lines'}[$i] += $counter[$i];
343                                 $sum += $counter[$i];
344                         }
345                         $NickData->{$main}{'lines_total'} = $sum;
346                 }
347
348                 @counter = $NickWordsCounter->get ($nick);
349                 if (@counter)
350                 {
351                         my $sum = 0;
352                         for (my $i = 0; $i < 24; $i++)
353                         {
354                                 $NickData->{$main}{'words'}[$i] += $counter[$i];
355                                 $sum += $counter[$i];
356                         }
357                         $NickData->{$main}{'words_total'} = $sum;
358                 }
359
360                 @counter = $NickWordsCounter->get ($nick);
361                 if (@counter)
362                 {
363                         my $sum = 0;
364                         for (my $i = 0; $i < 24; $i++)
365                         {
366                                 $NickData->{$main}{'words'}[$i] += $counter[$i];
367                                 $sum += $counter[$i];
368                         }
369                         $NickData->{$main}{'chars_total'} = $sum;
370                 }
371
372                 if (!defined ($QuoteData->{$main}))
373                 {
374                         $QuoteData->{$main} = [];
375                 }
376                 if (defined ($QuoteCache->{$nick}))
377                 {
378                         my @new = sort (sub { $b->[0] <=> $a->[0] }, @{$QuoteCache->{$nick}}, @{$QuoteData->{$main}});
379                         splice (@new, $QuoteCacheSize) if (scalar (@new) > $QuoteCacheSize);
380                         $QuoteData->{$main} = \@new;
381                 }
382         }
383 }
384
385 sub output
386 {
387         calculate ();
388         activetimes ();
389         ranking ();
390 }
391         
392 sub activetimes
393 {
394         my $max = 0;            # the most lines that were written in one hour..
395         my $total = 0;          # the total amount of lines we wrote..
396         my ($i, $j);            # used in for-loops
397         my $factor = 0;         # used to find a bar's height
398         my $newline = '';       # buffer variable..
399
400         my @data = @{$DATA->{'byhour'}};
401
402         my @img_urls = get_config ('vertical_images');
403         if (!@img_urls)
404         {
405                 @img_urls = qw#images/ver0n.png images/ver1n.png images/ver2n.png images/ver3n.png#;
406         }
407
408         my $fh = get_filehandle () or die;
409         
410 # this for loop looks for the most amount of lines in one hour and sets
411 # $most_lines
412         for ($i = 0; $i < 24; $i++)
413         {
414                 if (!defined ($data[$i]))
415                 {
416                         next;
417                 }
418
419                 $total += $data[$i];
420
421                 if ($data[$i] > $max)
422                 {
423                         $max = $data[$i];
424                 }
425         }
426
427         if (!$total)
428         {
429                 $total = 1;
430                 $max = 1;
431         }
432
433         $factor = (($BAR_HEIGHT - 1) / $max);
434
435         my $header = translate ('When do we actually talk here?');
436         print $fh "<h2>$header</h2>\n",
437         qq#<table class="hours_of_day">\n#,
438         qq#  <tr>\n#;
439
440 # this for circles through the four colors. Each color represents six hours.
441 # (4 * 6 hours = 24 hours)
442         for ($i = 0; $i <= 3; $i++)
443         {
444                 for ($j = 0; $j <= 5; $j++)
445                 {
446                         my $hour = (($i * 6) + $j);
447                         if (!defined ($data[$hour]))
448                         {
449                                 $data[$hour] = 0;
450                         }
451
452                         my $percent = 100 * ($data[$hour] / $total);
453                         my $height = int ($data[$hour] * $factor) + 1;
454                         my $img_url = $img_urls[$i];
455                         
456                         print $fh '    <td>', sprintf ("%2.1f", $percent),
457                         qq#%<br /><img src="$img_url" style="height: $height#,
458                         qq#px;" alt="" /></td>\n#;
459                 }
460         }
461
462         print $fh "  </tr>\n",
463         qq#  <tr class="hour_row">\n#;
464         print $fh map { "    <td>$_</td>\n" } (0 .. 23);
465         print $fh "  </tr>\n",
466         "</table>\n\n";
467 }
468
469 sub ranking
470 {
471         my $count = 0;
472
473         my @nicks = keys (%$NickData);
474
475         return unless (@nicks);
476         
477         my $max_lines = 1;
478         my $max_words = 1;
479         my $max_chars = 1;
480         
481         my $linescount = 0;
482
483         my $fh = get_filehandle () or die;
484
485         my $sort_field = lc ($SORT_BY);
486
487         my $trans;
488
489         my $tmp;
490         ($tmp) = sort { $NickData->{$b}{'lines_total'} <=> $NickData->{$a}{'lines_total'} } (@nicks);
491         $max_lines = $NickData->{$tmp}{'lines_total'} || 0;
492         
493         ($tmp) = sort { $NickData->{$b}{'words_total'} <=> $NickData->{$a}{'words_total'} } (@nicks);
494         $max_words = $NickData->{$tmp}{'words_total'} || 0;
495         
496         ($tmp) = sort { $NickData->{$b}{'chars_total'} <=> $NickData->{$a}{'chars_total'} } (@nicks);
497         $max_chars = $NickData->{$tmp}{'chars_total'} || 0;
498         
499         $trans = translate ('Most active nicks');
500         
501         print $fh "<h2>$trans</h2>\n";
502         if ($SORT_BY eq 'LINES')
503         {
504                 $trans = translate ('Nicks sorted by numbers of lines written');
505         }
506         elsif ($SORT_BY eq 'WORDS')
507         {
508                 $trans = translate ('Nicks sorted by numbers of words written');
509         }
510         else # ($SORT_BY eq 'CHARS')
511         {
512                 $trans = translate ('Nicks sorted by numbers of characters written');
513         }
514         print $fh "<p>($trans)</p>\n";
515
516         print $fh <<EOF;
517
518 <table class="big_ranking">
519   <tr>
520     <td class="invis">&nbsp;</td>
521 EOF
522         if ($DISPLAY_IMAGES)
523         {
524                 $trans = translate ('Image');
525                 print $fh "    <th>$trans</th>\n";
526         }
527         #if (true)
528         {
529                 $trans = translate ('Nick');
530                 print $fh "    <th>$trans</th>\n";
531         }
532         if ($DISPLAY_LINES ne 'NONE')
533         {
534                 $trans = translate ('Number of Lines');
535                 print $fh "    <th>$trans</th>\n";
536         }
537         if ($DISPLAY_WORDS ne 'NONE')
538         {
539                 $trans = translate ('Number of Words');
540                 print $fh "    <th>$trans</th>\n";
541         }
542         if ($DISPLAY_CHARS ne 'NONE')
543         {
544                 $trans = translate ('Number of Characters');
545                 print $fh "    <th>$trans</th>\n";
546         }
547         if ($DISPLAY_TIMES)
548         {
549                 $trans = translate ('When?');
550                 print $fh "    <th>$trans</th>\n";
551         }
552         
553         $trans = translate ('Random Quote');
554         print $fh "    <th>$trans</th>\n",
555         "  </tr>\n";
556
557         for (sort
558         {
559                 $NickData->{$b}{"${sort_field}_total"} <=> $NickData->{$a}{"${sort_field}_total"}
560         } (@nicks))
561         {
562                 my $nick = $_;
563                 my $ident = nick_to_ident ($nick);
564                 my $name  = ident_to_name ($ident);
565
566                 $linescount++;
567
568                 # As long as we didn't hit the 
569                 # $LongLines-limit we continue
570                 # our table..
571                 if ($linescount <= $LongLines)
572                 {
573                         my $quote = translate ('-- no quote available --');
574
575                         if (defined ($QuoteData->{$nick}))
576                         {
577                                 my $num = scalar (@{$QuoteData->{$nick}});
578                                 my $rand = int (rand ($num));
579                                 $quote = html_escape ($QuoteData->{$nick}[$rand]);
580                         }
581
582                         my $link = '';
583                         my $image = '';
584                         my $realname = '';
585                         if ($name)
586                         {
587                                 $link     = get_link ($name);
588                                 $image    = get_image ($name);
589                                 $realname = get_realname ($name);
590                         }
591                         
592                         print $fh "  <tr>\n",
593                         qq#    <td class="numeration"># . $linescount . "</td>\n";
594
595                         if ($DISPLAY_IMAGES)
596                         {
597                                 if ($DEFAULT_IMAGE and !$image)
598                                 {
599                                         $image = $DEFAULT_IMAGE;
600                                 }
601                                 
602                                 print $fh qq#    <td class="image">#;
603                                 if ($image)
604                                 {
605                                         if ($link)
606                                         {
607                                                 print $fh qq#<a href="$link">#;
608                                         }
609                                         print $fh qq#<img src="$image" alt="$name" />#;
610                                         if ($link)
611                                         {
612                                                 print $fh "</a>";
613                                         }
614                                 }
615                                 else
616                                 {
617                                         print $fh '&nbsp;';
618                                 }
619                                 print $fh "</td>\n";
620                         }
621                         
622                         my $title = $realname;
623                         if (!$title)
624                         {
625                                 $title = "User: $name; " if ($name);
626                                 $title .= "Ident: $ident";
627                         }
628                         print $fh qq#    <td class="nick" title="$title">#;
629
630                         if ($link)
631                         {
632                                 print $fh qq#<a href="$link">$name</a></td>\n#
633                         }
634                         else
635                         {
636                                 print $fh qq#$name</td>\n#;
637                         }
638                 
639                         if ($DISPLAY_LINES ne 'NONE')
640                         {
641                                 print $fh qq#    <td class="bar">#;
642                                 if (($DISPLAY_LINES eq 'BOTH') or ($DISPLAY_LINES eq 'BAR'))
643                                 {
644                                         my $code = bar ($max_lines, $NickData->{$nick}{'lines'});
645                                         print $fh $code;
646                                 }
647                                 print $fh '&nbsp;' if ($DISPLAY_LINES eq 'BOTH');
648                                 if (($DISPLAY_LINES eq 'BOTH') or ($DISPLAY_LINES eq 'NUMBER'))
649                                 {
650                                         print $fh $NickData->{$nick}{'lines_total'};
651                                 }
652                                 print $fh "</td>\n";
653                         }
654
655                         if ($DISPLAY_WORDS ne 'NONE')
656                         {
657                                 print $fh qq#    <td class="bar">#;
658                                 if (($DISPLAY_WORDS eq 'BOTH') or ($DISPLAY_WORDS eq 'BAR'))
659                                 {
660                                         my $code = bar ($max_words, $NickData->{$nick}{'words'});
661                                         print $fh $code;
662                                 }
663                                 print $fh '&nbsp;' if ($DISPLAY_WORDS eq 'BOTH');
664                                 if (($DISPLAY_WORDS eq 'BOTH') or ($DISPLAY_WORDS eq 'NUMBER'))
665                                 {
666                                         print $fh $NickData->{$nick}{'words_total'};
667                                 }
668                                 print $fh "</td>\n";
669                         }
670
671                         if ($DISPLAY_CHARS ne 'NONE')
672                         {
673                                 print $fh qq#    <td class="bar">#;
674                                 if (($DISPLAY_CHARS eq 'BOTH') or ($DISPLAY_CHARS eq 'BAR'))
675                                 {
676                                         my $code = bar ($max_chars, $NickData->{$nick}{'chars'});
677                                         print $fh $code;
678                                 }
679                                 print $fh '&nbsp;' if ($DISPLAY_CHARS eq 'BOTH');
680                                 if (($DISPLAY_CHARS eq 'BOTH') or ($DISPLAY_CHARS eq 'NUMBER'))
681                                 {
682                                         print $fh $NickData->{$nick}{'chars_total'};
683                                 }
684                                 print $fh "</td>\n";
685                         }
686
687                         if ($DISPLAY_TIMES)
688                         {
689                                 my $code = bar ($NickData->{$nick}{'chars_total'}, $NickData->{$nick}{'chars'});
690                                 print $fh qq#    <td class="bar">$code</td>\n#;
691                         }
692
693                         print $fh qq#    <td class="quote">$quote</td>\n#,
694                         qq#  </tr>\n#;
695                         
696                         if ($linescount == $LongLines)
697                         {
698                                 print $fh "</table>\n\n";
699                         }
700                 }
701
702                 # Ok, we have too many people to
703                 # list them all so we start a
704                 # smaller table and just list the
705                 # names.. (Six names per line..)
706                 elsif ($linescount <= ($LongLines + 6 * $ShortLines))
707                 {
708                         my $row_in_this_table = int (($linescount - $LongLines - 1) / 6);
709                         my $col_in_this_table = ($linescount - $LongLines - 1) % 6;
710
711                         my $total = 0;
712                         if ($SORT_BY eq 'LINES')
713                         {
714                                 $total = $DATA->{'byname'}{$name}{'lines'};
715                         }
716                         elsif ($SORT_BY eq 'WORDS')
717                         {
718                                 $total = $DATA->{'byname'}{$name}{'words'};
719                         }
720                         else # ($SORT_BY eq 'CHARS')
721                         {
722                                 $total = $DATA->{'byname'}{$name}{'chars'};
723                         }
724                         
725                         if ($row_in_this_table == 0 and $col_in_this_table == 0)
726                         {
727                                 $trans = translate ("They didn't write so much");
728                                 print $fh "<h2>$trans</h2>\n",
729                                 qq#<table class="small_ranking">\n#,
730                                 qq#  <tr>\n#;
731                         }
732                         
733                         if ($col_in_this_table == 0 and $row_in_this_table != 0)
734                         {
735                                 print $fh "  </tr>\n",
736                                 qq#  <tr>\n#;
737                         }
738                         
739                         print $fh "    <td>$name ($total)</td>\n";
740                         
741                         if ($row_in_this_table == $ShortLines and $col_in_this_table == 5)
742                         {
743                                 print $fh "  </tr>\n",
744                                 qq#</table>\n\n#;
745                         }
746                 }
747
748                 # There is no else. There are
749                 # just too many people around.
750                 # I might add a "There are xyz
751                 # unmentioned nicks"-line..
752         }
753
754         if (($linescount > $LongLines)
755                         and ($linescount <= ($LongLines + 6 * $ShortLines)))
756         {
757                 my $col = ($linescount - $LongLines - 1) % 6;
758
759                 while ($col < 5)
760                 {
761                         print $fh qq#    <td>&nbsp;</td>\n#;
762                         $col++;
763                 }
764
765                 print $fh "  </tr>\n";
766         }
767
768         if ($linescount != $LongLines)
769         {
770                 print $fh "</table>\n\n";
771         }
772 }
773
774 # this is called by "&ranking ();" and prints the horizontal usage-bar in the
775 # detailed nick-table
776 sub bar
777 {
778         my $max_num = shift;
779
780         my $source = shift;
781
782         confess unless (ref ($source eq 'ARRAY'));
783
784         # BAR_WIDTH is a least 10
785         my $max_width = $BAR_WIDTH - 4;
786         my $factor = 1;
787         my $retval = '';
788
789         my $i;
790         my $j;
791
792         if (!$max_num) { return ($retval); }
793         $factor = $max_width / $max_num;
794
795         for ($i = 0; $i < 4; $i++)
796         {
797                 my $sum = 0;
798                 my $width = 1;
799                 my $img = $H_IMAGES[$i];
800
801                 for ($j = 0; $j < 6; $j++)
802                 {
803                         my $hour = ($i * 6) + $j;
804                         $sum += $source->[$hour];
805                 }
806
807                 $width += int (0.5 + ($sum * $factor));
808                 
809                 $retval .= qq#<img src="$img" style="width: # . $width . q#px"#;
810                 if ($i == 0) { $retval .= qq# class="first"#; }
811                 elsif ($i == 3) { $retval .= qq# class="last"#; }
812                 $retval .= ' alt="" />';
813         }
814
815         return ($retval);
816 }
817
818 =head1 AUTHOR
819
820 Florian octo Forster, E<lt>octo at verplant.orgE<gt>
821
822 =cut