3f01666c12310f35480cb3690b7303e1adcd1123
[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 $factor = 0;         # used to find a bar's height
397
398         my @data = 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);
399
400         my @img_urls = get_config ('vertical_images');
401         if (!@img_urls)
402         {
403                 @img_urls = qw#images/ver0n.png images/ver1n.png images/ver2n.png images/ver3n.png#;
404         }
405
406         my $fh = get_filehandle () or die;
407         
408 # this for loop looks for the most amount of lines in one hour and sets
409 # $most_lines
410         for (keys %$NickData)
411         {
412                 my $nick = shift;
413
414                 for (my $i = 0; $i < 24; $i++)
415                 {
416                         $data[$i] += $NickData->{$nick}{'chars'}[$i];
417                 }
418         }
419
420         for (my $i = 0; $i < 24; $i++)
421         {
422                 $max = $data[$i] if ($max < $data[$i]);
423                 $total += $data[$i];
424         }
425
426         if (!$total)
427         {
428                 $total = 1;
429                 $max = 1;
430         }
431
432         $factor = (($BAR_HEIGHT - 1) / $max);
433
434         my $header = translate ('When do we actually talk here?');
435         print $fh "<h2>$header</h2>\n",
436         qq#<table class="hours_of_day">\n#,
437         qq#  <tr>\n#;
438
439 # this for circles through the four colors. Each color represents six hours.
440 # (4 * 6 hours = 24 hours)
441         for (my $i = 0; $i <= 3; $i++)
442         {
443                 for (my $j = 0; $j <= 5; $j++)
444                 {
445                         my $hour = (($i * 6) + $j);
446                         if (!defined ($data[$hour]))
447                         {
448                                 $data[$hour] = 0;
449                         }
450
451                         my $percent = 100 * ($data[$hour] / $total);
452                         my $height = int ($data[$hour] * $factor) + 1;
453                         my $img_url = $img_urls[$i];
454                         
455                         print $fh '    <td>', sprintf ("%2.1f", $percent),
456                         qq#%<br /><img src="$img_url" style="height: $height#,
457                         qq#px;" alt="" /></td>\n#;
458                 }
459         }
460
461         print $fh "  </tr>\n",
462         qq#  <tr class="hour_row">\n#;
463         print $fh map { "    <td>$_</td>\n" } (0 .. 23);
464         print $fh "  </tr>\n",
465         "</table>\n\n";
466 }
467
468 sub ranking
469 {
470         my $count = 0;
471
472         my @nicks = keys (%$NickData);
473
474         return unless (@nicks);
475         
476         my $max_lines = 1;
477         my $max_words = 1;
478         my $max_chars = 1;
479         
480         my $linescount = 0;
481
482         my $fh = get_filehandle () or die;
483
484         my $sort_field = lc ($SORT_BY);
485
486         my $trans;
487
488         my $tmp;
489         ($tmp) = sort { $NickData->{$b}{'lines_total'} <=> $NickData->{$a}{'lines_total'} } (@nicks);
490         $max_lines = $NickData->{$tmp}{'lines_total'} || 0;
491         
492         ($tmp) = sort { $NickData->{$b}{'words_total'} <=> $NickData->{$a}{'words_total'} } (@nicks);
493         $max_words = $NickData->{$tmp}{'words_total'} || 0;
494         
495         ($tmp) = sort { $NickData->{$b}{'chars_total'} <=> $NickData->{$a}{'chars_total'} } (@nicks);
496         $max_chars = $NickData->{$tmp}{'chars_total'} || 0;
497         
498         $trans = translate ('Most active nicks');
499         
500         print $fh "<h2>$trans</h2>\n";
501         if ($SORT_BY eq 'LINES')
502         {
503                 $trans = translate ('Nicks sorted by numbers of lines written');
504         }
505         elsif ($SORT_BY eq 'WORDS')
506         {
507                 $trans = translate ('Nicks sorted by numbers of words written');
508         }
509         else # ($SORT_BY eq 'CHARS')
510         {
511                 $trans = translate ('Nicks sorted by numbers of characters written');
512         }
513         print $fh "<p>($trans)</p>\n";
514
515         print $fh <<EOF;
516
517 <table class="big_ranking">
518   <tr>
519     <td class="invis">&nbsp;</td>
520 EOF
521         if ($DISPLAY_IMAGES)
522         {
523                 $trans = translate ('Image');
524                 print $fh "    <th>$trans</th>\n";
525         }
526         #if (true)
527         {
528                 $trans = translate ('Nick');
529                 print $fh "    <th>$trans</th>\n";
530         }
531         if ($DISPLAY_LINES ne 'NONE')
532         {
533                 $trans = translate ('Number of Lines');
534                 print $fh "    <th>$trans</th>\n";
535         }
536         if ($DISPLAY_WORDS ne 'NONE')
537         {
538                 $trans = translate ('Number of Words');
539                 print $fh "    <th>$trans</th>\n";
540         }
541         if ($DISPLAY_CHARS ne 'NONE')
542         {
543                 $trans = translate ('Number of Characters');
544                 print $fh "    <th>$trans</th>\n";
545         }
546         if ($DISPLAY_TIMES)
547         {
548                 $trans = translate ('When?');
549                 print $fh "    <th>$trans</th>\n";
550         }
551         
552         $trans = translate ('Random Quote');
553         print $fh "    <th>$trans</th>\n",
554         "  </tr>\n";
555
556         for (sort
557         {
558                 $NickData->{$b}{"${sort_field}_total"} <=> $NickData->{$a}{"${sort_field}_total"}
559         } (@nicks))
560         {
561                 my $nick = $_;
562                 my $ident = nick_to_ident ($nick);
563                 my $name  = ident_to_name ($ident);
564
565                 $linescount++;
566
567                 # As long as we didn't hit the 
568                 # $LongLines-limit we continue
569                 # our table..
570                 if ($linescount <= $LongLines)
571                 {
572                         my $quote = translate ('-- no quote available --');
573
574                         if (defined ($QuoteData->{$nick}))
575                         {
576                                 my $num = scalar (@{$QuoteData->{$nick}});
577                                 my $rand = int (rand ($num));
578                                 $quote = html_escape ($QuoteData->{$nick}[$rand]);
579                         }
580
581                         my $link = '';
582                         my $image = '';
583                         my $realname = '';
584                         if ($name)
585                         {
586                                 $link     = get_link ($name);
587                                 $image    = get_image ($name);
588                                 $realname = get_realname ($name);
589                         }
590                         
591                         print $fh "  <tr>\n",
592                         qq#    <td class="numeration"># . $linescount . "</td>\n";
593
594                         if ($DISPLAY_IMAGES)
595                         {
596                                 if ($DEFAULT_IMAGE and !$image)
597                                 {
598                                         $image = $DEFAULT_IMAGE;
599                                 }
600                                 
601                                 print $fh qq#    <td class="image">#;
602                                 if ($image)
603                                 {
604                                         if ($link)
605                                         {
606                                                 print $fh qq#<a href="$link">#;
607                                         }
608                                         print $fh qq#<img src="$image" alt="$name" />#;
609                                         if ($link)
610                                         {
611                                                 print $fh "</a>";
612                                         }
613                                 }
614                                 else
615                                 {
616                                         print $fh '&nbsp;';
617                                 }
618                                 print $fh "</td>\n";
619                         }
620                         
621                         my $title = $realname;
622                         if (!$title)
623                         {
624                                 $title = "User: $name; " if ($name);
625                                 $title .= "Ident: $ident";
626                         }
627                         print $fh qq#    <td class="nick" title="$title">#;
628
629                         if ($link)
630                         {
631                                 print $fh qq#<a href="$link">$name</a></td>\n#
632                         }
633                         else
634                         {
635                                 print $fh qq#$name</td>\n#;
636                         }
637                 
638                         if ($DISPLAY_LINES ne 'NONE')
639                         {
640                                 print $fh qq#    <td class="bar">#;
641                                 if (($DISPLAY_LINES eq 'BOTH') or ($DISPLAY_LINES eq 'BAR'))
642                                 {
643                                         my $code = bar ($max_lines, $NickData->{$nick}{'lines'});
644                                         print $fh $code;
645                                 }
646                                 print $fh '&nbsp;' if ($DISPLAY_LINES eq 'BOTH');
647                                 if (($DISPLAY_LINES eq 'BOTH') or ($DISPLAY_LINES eq 'NUMBER'))
648                                 {
649                                         print $fh $NickData->{$nick}{'lines_total'};
650                                 }
651                                 print $fh "</td>\n";
652                         }
653
654                         if ($DISPLAY_WORDS ne 'NONE')
655                         {
656                                 print $fh qq#    <td class="bar">#;
657                                 if (($DISPLAY_WORDS eq 'BOTH') or ($DISPLAY_WORDS eq 'BAR'))
658                                 {
659                                         my $code = bar ($max_words, $NickData->{$nick}{'words'});
660                                         print $fh $code;
661                                 }
662                                 print $fh '&nbsp;' if ($DISPLAY_WORDS eq 'BOTH');
663                                 if (($DISPLAY_WORDS eq 'BOTH') or ($DISPLAY_WORDS eq 'NUMBER'))
664                                 {
665                                         print $fh $NickData->{$nick}{'words_total'};
666                                 }
667                                 print $fh "</td>\n";
668                         }
669
670                         if ($DISPLAY_CHARS ne 'NONE')
671                         {
672                                 print $fh qq#    <td class="bar">#;
673                                 if (($DISPLAY_CHARS eq 'BOTH') or ($DISPLAY_CHARS eq 'BAR'))
674                                 {
675                                         my $code = bar ($max_chars, $NickData->{$nick}{'chars'});
676                                         print $fh $code;
677                                 }
678                                 print $fh '&nbsp;' if ($DISPLAY_CHARS eq 'BOTH');
679                                 if (($DISPLAY_CHARS eq 'BOTH') or ($DISPLAY_CHARS eq 'NUMBER'))
680                                 {
681                                         print $fh $NickData->{$nick}{'chars_total'};
682                                 }
683                                 print $fh "</td>\n";
684                         }
685
686                         if ($DISPLAY_TIMES)
687                         {
688                                 my $code = bar ($NickData->{$nick}{'chars_total'}, $NickData->{$nick}{'chars'});
689                                 print $fh qq#    <td class="bar">$code</td>\n#;
690                         }
691
692                         print $fh qq#    <td class="quote">$quote</td>\n#,
693                         qq#  </tr>\n#;
694                         
695                         if ($linescount == $LongLines)
696                         {
697                                 print $fh "</table>\n\n";
698                         }
699                 }
700
701                 # Ok, we have too many people to
702                 # list them all so we start a
703                 # smaller table and just list the
704                 # names.. (Six names per line..)
705                 elsif ($linescount <= ($LongLines + 6 * $ShortLines))
706                 {
707                         my $row_in_this_table = int (($linescount - $LongLines - 1) / 6);
708                         my $col_in_this_table = ($linescount - $LongLines - 1) % 6;
709
710                         my $total = 0;
711                         if ($SORT_BY eq 'LINES')
712                         {
713                                 $total = $NickData->{$nick}{'lines_total'};
714                         }
715                         elsif ($SORT_BY eq 'WORDS')
716                         {
717                                 $total = $NickData->{$nick}{'words_total'};
718                         }
719                         else # ($SORT_BY eq 'CHARS')
720                         {
721                                 $total = $NickData->{$nick}{'chars_total'};
722                         }
723
724                         my $title = $name ? get_realname ($name) : '';
725                         if (!$title)
726                         {
727                                 $title = "User: $name; " if ($name);
728                                 $title .= "Ident: $ident";
729                         }
730                         
731                         if ($row_in_this_table == 0 and $col_in_this_table == 0)
732                         {
733                                 $trans = translate ("They didn't write so much");
734                                 print $fh "<h2>$trans</h2>\n",
735                                 qq#<table class="small_ranking">\n#,
736                                 qq#  <tr>\n#;
737                         }
738                         
739                         if ($col_in_this_table == 0 and $row_in_this_table != 0)
740                         {
741                                 print $fh "  </tr>\n",
742                                 qq#  <tr>\n#;
743                         }
744                         
745                         print $fh qq#    <td title="$title">$name ($total)</td>\n#;
746                         
747                         if ($row_in_this_table == $ShortLines and $col_in_this_table == 5)
748                         {
749                                 print $fh "  </tr>\n",
750                                 qq#</table>\n\n#;
751                         }
752                 }
753
754                 # There is no else. There are
755                 # just too many people around.
756                 # I might add a "There are xyz
757                 # unmentioned nicks"-line..
758         }
759
760         if (($linescount > $LongLines)
761                         and ($linescount <= ($LongLines + 6 * $ShortLines)))
762         {
763                 my $col = ($linescount - $LongLines - 1) % 6;
764
765                 while ($col < 5)
766                 {
767                         print $fh qq#    <td>&nbsp;</td>\n#;
768                         $col++;
769                 }
770
771                 print $fh "  </tr>\n";
772         }
773
774         if ($linescount != $LongLines)
775         {
776                 print $fh "</table>\n\n";
777         }
778 }
779
780 # this is called by "&ranking ();" and prints the horizontal usage-bar in the
781 # detailed nick-table
782 sub bar
783 {
784         my $max_num = shift;
785
786         my $source = shift;
787
788         confess unless (ref ($source eq 'ARRAY'));
789
790         # BAR_WIDTH is a least 10
791         my $max_width = $BAR_WIDTH - 4;
792         my $factor = 1;
793         my $retval = '';
794
795         my $i;
796         my $j;
797
798         if (!$max_num) { return ($retval); }
799         $factor = $max_width / $max_num;
800
801         for ($i = 0; $i < 4; $i++)
802         {
803                 my $sum = 0;
804                 my $width = 1;
805                 my $img = $H_IMAGES[$i];
806
807                 for ($j = 0; $j < 6; $j++)
808                 {
809                         my $hour = ($i * 6) + $j;
810                         $sum += $source->[$hour];
811                 }
812
813                 $width += int (0.5 + ($sum * $factor));
814                 
815                 $retval .= qq#<img src="$img" style="width: # . $width . q#px"#;
816                 if ($i == 0) { $retval .= qq# class="first"#; }
817                 elsif ($i == 3) { $retval .= qq# class="last"#; }
818                 $retval .= ' alt="" />';
819         }
820
821         return ($retval);
822 }
823
824 =head1 AUTHOR
825
826 Florian octo Forster, E<lt>octo at verplant.orgE<gt>
827
828 =cut