1 package Onis::Plugins::Core;
6 use Carp (qw(confess));
15 Plugin for the main table and the hourly-statistics. This is the most
16 complicated plugin so far.
20 use Onis::Config (qw(get_config));
21 use Onis::Html (qw(html_escape get_filehandle));
22 use Onis::Language (qw(translate));
23 use Onis::Users (qw(get_realname get_link get_image chatter_to_name));
24 use Onis::Data::Core (qw(get_all_nicks nick_to_ident ident_to_nick get_main_nick register_plugin));
25 use Onis::Data::Persistent ();
27 @Onis::Plugins::Core::EXPORT_OK = (qw(get_core_nick_counters get_sorted_nicklist nick_is_in_main_table));
28 @Onis::Plugins::Core::ISA = ('Exporter');
30 our $NickLinesCounter = Onis::Data::Persistent->new ('NickLinesCounter', 'nick',
32 lines00 lines01 lines02 lines03 lines04 lines05 lines06 lines07 lines08 lines09 lines10 lines11
33 lines12 lines13 lines14 lines15 lines16 lines17 lines18 lines19 lines20 lines21 lines22 lines23
36 our $NickWordsCounter = Onis::Data::Persistent->new ('NickWordsCounter', 'nick',
38 words00 words01 words02 words03 words04 words05 words06 words07 words08 words09 words10 words11
39 words12 words13 words14 words15 words16 words17 words18 words19 words20 words21 words22 words23
42 our $NickCharsCounter = Onis::Data::Persistent->new ('NickCharsCounter', 'nick',
44 chars00 chars01 chars02 chars03 chars04 chars05 chars06 chars07 chars08 chars09 chars10 chars11
45 chars12 chars13 chars14 chars15 chars16 chars17 chars18 chars19 chars20 chars21 chars22 chars23
49 our $QuoteCache = Onis::Data::Persistent->new ('QuoteCache', 'key', qw(epoch text));
50 our $QuotePtr = Onis::Data::Persistent->new ('QuotePtr', 'nick', qw(pointer));
52 our $QuoteData = {}; # Is generated before output. Nicks are merged according to Data::Core.
53 our $NickData = {}; # Same as above, but for nicks rather than quotes.
54 our $SortedNicklist = [];
56 our $NicksInMainTable = {};
58 our @H_IMAGES = qw#dark-theme/h-red.png dark-theme/h-blue.png dark-theme/h-yellow.png dark-theme/h-green.png#;
59 our $QuoteCacheSize = 10;
63 our $SORT_BY = 'LINES';
64 our $DISPLAY_LINES = 'BOTH';
65 our $DISPLAY_WORDS = 'NONE';
66 our $DISPLAY_CHARS = 'NONE';
67 our $DISPLAY_TIMES = 0;
68 our $DISPLAY_IMAGES = 0;
69 our $DEFAULT_IMAGE = '';
70 our $BAR_HEIGHT = 130;
75 =head1 CONFIGURATION OPTIONS
79 =item B<quote_cache_size>: I<10>
81 Sets how many quotes are cached and, at the end, one is chosen at random.
85 if (get_config ('quote_cache_size'))
87 my $tmp = get_config ('quote_cache_size');
89 $QuoteCacheSize = $tmp if ($tmp);
92 =item B<quote_min>: I<30>
94 Minimum number of characters in a line to be included in the quote-cache.
98 if (get_config ('quote_min'))
100 my $tmp = get_config ('quote_min');
102 $QuoteMin = $tmp if ($tmp);
104 =item B<quote_max>: I<80>
106 Maximum number of characters in a line to be included in the quote-cache.
110 if (get_config ('quote_max'))
112 my $tmp = get_config ('quote_max');
114 $QuoteMax = $tmp if ($tmp);
117 =item B<min_word_length>: I<5>
119 Sets how many word-characters in a row are considered to be a word. Or, in more
120 normal terms: Sets the minimum length for words..
124 if (get_config ('min_word_length'))
126 my $tmp = get_config ('min_word_length');
128 $WORD_LENGTH = $tmp if ($tmp);
131 =item B<display_lines>: I<BOTH>
133 Choses wether to display B<lines> as I<BAR>, I<NUMBER>, I<BOTH> or not at all
138 if (get_config ('display_lines'))
140 my $tmp = get_config ('display_lines');
143 if (($tmp eq 'NONE') or ($tmp eq 'BAR') or ($tmp eq 'NUMBER') or ($tmp eq 'BOTH'))
145 $DISPLAY_LINES = $tmp;
149 $tmp = get_config ('display_lines');
150 print STDERR $/, __FILE__, ": ``display_lines'' has been set to the invalid value ``$tmp''. ",
151 $/, __FILE__, ": Valid values are ``none'', ``bar'', ``number'' and ``both''. Using default value ``both''.";
155 =item B<display_words>: I<NONE>
161 if (get_config ('display_words'))
163 my $tmp = get_config ('display_words');
166 if (($tmp eq 'NONE') or ($tmp eq 'BAR') or ($tmp eq 'NUMBER') or ($tmp eq 'BOTH'))
168 $DISPLAY_WORDS = $tmp;
172 $tmp = get_config ('display_words');
173 print STDERR $/, __FILE__, ": ``display_words'' has been set to the invalid value ``$tmp''. ",
174 $/, __FILE__, ": Valid values are ``none'', ``bar'', ``number'' and ``both''. Using default value ``none''.";
178 =item B<display_chars>: I<NONE>
184 if (get_config ('display_chars'))
186 my $tmp = get_config ('display_chars');
189 if (($tmp eq 'NONE') or ($tmp eq 'BAR') or ($tmp eq 'NUMBER') or ($tmp eq 'BOTH'))
191 $DISPLAY_CHARS = $tmp;
195 $tmp = get_config ('display_chars');
196 print STDERR $/, __FILE__, ": ``display_chars'' has been set to the invalid value ``$tmp''. ",
197 $/, __FILE__, ": Valid values are ``none'', ``bar'', ``number'' and ``both''. Using default value ``none''.";
201 =item B<display_times>: I<false>
203 Wether or not to display a fixed width bar that shows when a user is most
208 if (get_config ('display_times'))
210 my $tmp = get_config ('display_times');
212 if ($tmp =~ m/true|on|yes/i)
216 elsif ($tmp =~ m/false|off|no/i)
222 print STDERR $/, __FILE__, ": ``display_times'' has been set to the invalid value ``$tmp''. ",
223 $/, __FILE__, ": Valid values are ``true'' and ``false''. Using default value ``false''.";
227 =item B<display_images>: I<false>
229 Wether or not to display images in the main ranking.
233 if (get_config ('display_images'))
235 my $tmp = get_config ('display_images');
237 if ($tmp =~ m/true|on|yes/i)
241 elsif ($tmp =~ m/false|off|no/i)
247 print STDERR $/, __FILE__, ": ``display_times'' has been set to the invalid value ``$tmp''. ",
248 $/, __FILE__, ": Valid values are ``true'' and ``false''. Using default value ``false''.";
252 =item B<default_image>: I<http://www.url.org/image.png>
254 Sets the URL to the default image. This is included as-is in the HTML. You have
255 to take care of (absolute) paths yourself.
259 if (get_config ('default_image'))
261 $DEFAULT_IMAGE = get_config ('default_image');
264 =item B<sort_by>: I<LINES>
266 Sets by which field the output has to be sorted. This is completely independent
267 from B<display_lines>, B<display_words> and B<display_chars>. Valid options are
268 I<LINES>, I<WORDS> and I<CHARS>.
272 if (get_config ('sort_by'))
274 my $tmp = get_config ('sort_by');
277 if (($tmp eq 'LINES') or ($tmp eq 'WORDS') or ($tmp eq 'CHARS'))
283 $tmp = get_config ('sort_by');
284 print STDERR $/, __FILE__, ": ``sort_by'' has been set to the invalid value ``$tmp''. ",
285 $/, __FILE__, ": Valid values are ``lines'' and ``words''. Using default value ``lines''.";
289 =item B<horizontal_images>: I<image1>, I<image2>, I<image3>, I<image4>
291 Sets the B<four> images used for horizontal bars/graphs. As above: You have to
292 take care of correctness of paths yourself.
296 if (get_config ('horizontal_images'))
298 my @tmp = get_config ('horizontal_images');
301 if (scalar (@tmp) != 4)
303 print STDERR $/, __FILE__, ": The number of horizontal images is not four. The output might look weird.", $/;
306 for ($i = 0; $i < 4; $i++)
308 if (!defined ($tmp[$i]))
313 $H_IMAGES[$i] = $tmp[$i];
317 =item B<bar_height>: I<130>
319 Sets the height (in pixels) of the highest vertical graph.
323 if (get_config ('bar_height'))
325 my $tmp = get_config ('bar_height');
327 $BAR_HEIGHT = $tmp if ($tmp >= 10);
330 =item B<bar_width>: I<100>
332 Sets the width (in pixels) of the widest horizontal graph.
336 if (get_config ('bar_width'))
338 my $tmp = get_config ('bar_width');
340 $BAR_WIDTH = $tmp if ($tmp >= 10);
343 =item B<longlines>: I<50>
345 Sets the number of rows of the main ranking table.
349 if (get_config ('longlines'))
351 my $tmp = get_config ('longlines');
353 $LongLines = $tmp if ($tmp);
356 =item B<shortlines>: I<10>
358 Sets the number of rows of the "they didn't write so much" table. There are six
359 persons per line; you set the number of lines.
365 if (get_config ('shortlines'))
367 my $tmp = get_config ('shortlines');
369 if ($tmp or ($tmp == 0))
375 register_plugin ('TEXT', \&add);
376 register_plugin ('ACTION', \&add);
377 register_plugin ('OUTPUT', \&output);
379 my $VERSION = '$Id$';
380 print STDERR $/, __FILE__, ": $VERSION" if ($::DEBUG);
388 my $nick = $data->{'nick'};
389 my $ident = $data->{'ident'};
390 my $hour = int ($data->{'hour'});
391 my $host = $data->{'host'};
392 my $text = $data->{'text'};
393 my $type = $data->{'type'};
394 my $time = $data->{'epoch'};
396 my $words = scalar (@{$data->{'words'}});
397 my $chars = length ($text);
399 if ($type eq 'ACTION')
401 $chars -= (length ($nick) + 3);
404 my @counter = $NickLinesCounter->get ($nick);
407 @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);
410 $NickLinesCounter->put ($nick, @counter);
412 @counter = $NickWordsCounter->get ($nick);
415 @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);
417 $counter[$hour] += $words;
418 $NickWordsCounter->put ($nick, @counter);
420 @counter = $NickCharsCounter->get ($nick);
423 @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);
425 $counter[$hour] += $chars;
426 $NickCharsCounter->put ($nick, @counter);
428 if ((length ($text) >= $QuoteMin)
429 and (length ($text) <= $QuoteMax))
431 my ($pointer) = $QuotePtr->get ($nick);
434 my $key = sprintf ("%s:%02i", $nick, $pointer);
436 $QuoteCache->put ($key, $time, $text);
438 $pointer = ($pointer + 1) % $QuoteCacheSize;
439 $QuotePtr->put ($nick, $pointer);
446 for (get_all_nicks ())
449 my $main = get_main_nick ($nick);
451 if (!defined ($NickData->{$main}))
455 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)],
456 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)],
457 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)],
464 my @counter = $NickLinesCounter->get ($nick);
468 for (my $i = 0; $i < 24; $i++)
470 $NickData->{$main}{'lines'}[$i] += $counter[$i];
471 $sum += $counter[$i];
473 $NickData->{$main}{'lines_total'} += $sum;
476 @counter = $NickWordsCounter->get ($nick);
480 for (my $i = 0; $i < 24; $i++)
482 $NickData->{$main}{'words'}[$i] += $counter[$i];
483 $sum += $counter[$i];
485 $NickData->{$main}{'words_total'} += $sum;
488 @counter = $NickCharsCounter->get ($nick);
492 for (my $i = 0; $i < 24; $i++)
494 $NickData->{$main}{'chars'}[$i] += $counter[$i];
495 $sum += $counter[$i];
497 $NickData->{$main}{'chars_total'} += $sum;
500 if (!defined ($QuoteData->{$main}))
502 $QuoteData->{$main} = [];
506 for ($QuoteCache->keys ())
509 my ($nick, $num) = split (m/:/, $key);
510 my $main = get_main_nick ($nick);
512 my ($epoch, $text) = $QuoteCache->get ($key);
513 die unless (defined ($text));
515 if (!defined ($QuoteData->{$main}))
519 elsif (scalar (@{$QuoteData->{$main}}) < $QuoteCacheSize)
521 push (@{$QuoteData->{$main}}, [$epoch, $text]);
528 for (my $i = 0; $i < $QuoteCacheSize; $i++)
530 if ($QuoteData->{$main}[$i][0] < $min)
533 $min = $QuoteData->{$main}[$i][0];
539 $QuoteData->{$main}[$insert] = [$epoch, $text];
554 my $max = 0; # the most lines that were written in one hour..
555 my $total = 0; # the total amount of lines we wrote..
556 my $factor = 0; # used to find a bar's height
558 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);
560 my @img_urls = get_config ('vertical_images');
563 @img_urls = qw#images/ver0n.png images/ver1n.png images/ver2n.png images/ver3n.png#;
566 my $fh = get_filehandle () or die;
568 # this for loop looks for the most amount of lines in one hour and sets
570 for (keys %$NickData)
574 for (my $i = 0; $i < 24; $i++)
576 $data[$i] += $NickData->{$nick}{'chars'}[$i];
580 for (my $i = 0; $i < 24; $i++)
582 $max = $data[$i] if ($max < $data[$i]);
592 $factor = (($BAR_HEIGHT - 1) / $max);
594 my $header = translate ('When do we actually talk here?');
595 print $fh "<h2>$header</h2>\n",
596 qq#<table class="hours">\n#,
597 qq# <tr class="bars">\n#;
599 # this for circles through the four colors. Each color represents six hours.
600 # (4 * 6 hours = 24 hours)
601 for (my $i = 0; $i <= 3; $i++)
603 for (my $j = 0; $j < 6; $j++)
605 my $hour = (($i * 6) + $j);
606 if (!defined ($data[$hour]))
611 my $height = sprintf ("%.2f", 95 * $data[$hour] / $max);
612 my $img = $img_urls[$i];
614 print $fh qq# <td class="bar vertical"><img src="$img" class="first last" style="height: $height\%;" alt="" /></td>\n#;
617 print $fh qq# </tr>\n <tr class="counter">\n#;
618 for (my $i = 0; $i < 24; $i++)
620 my $percent = sprintf ("%.1f", 100 * $data[$i] / $total);
621 print $fh qq# <td class="counter">$percent\%</td>\n#;
624 print $fh " </tr>\n",
625 qq# <tr class="numeration">\n#;
626 print $fh map { qq# <td class="numeration">$_</td>\n# } (0 .. 23);
627 print $fh " </tr>\n",
635 my @nicks = keys (%$NickData);
637 return unless (@nicks);
645 my $fh = get_filehandle () or die;
647 my $sort_field = lc ($SORT_BY);
652 ($tmp) = sort { $NickData->{$b}{'lines_total'} <=> $NickData->{$a}{'lines_total'} } (@nicks);
653 $max_lines = $NickData->{$tmp}{'lines_total'} || 0;
655 ($tmp) = sort { $NickData->{$b}{'words_total'} <=> $NickData->{$a}{'words_total'} } (@nicks);
656 $max_words = $NickData->{$tmp}{'words_total'} || 0;
658 ($tmp) = sort { $NickData->{$b}{'chars_total'} <=> $NickData->{$a}{'chars_total'} } (@nicks);
659 $max_chars = $NickData->{$tmp}{'chars_total'} || 0;
661 $trans = translate ('Most active nicks');
663 print $fh "<h2>$trans</h2>\n";
664 if ($SORT_BY eq 'LINES')
666 $trans = translate ('Nicks sorted by numbers of lines written');
668 elsif ($SORT_BY eq 'WORDS')
670 $trans = translate ('Nicks sorted by numbers of words written');
672 else # ($SORT_BY eq 'CHARS')
674 $trans = translate ('Nicks sorted by numbers of characters written');
676 print $fh "<p>($trans)</p>\n";
680 <table class="big_ranking">
682 <td class="invis"> </td>
686 $trans = translate ('Image');
687 print $fh " <th>$trans</th>\n";
691 $trans = translate ('Nick');
692 print $fh " <th>$trans</th>\n";
694 if ($DISPLAY_LINES ne 'NONE')
696 $trans = translate ('Number of Lines');
697 print $fh " <th>$trans</th>\n";
699 if ($DISPLAY_WORDS ne 'NONE')
701 $trans = translate ('Number of Words');
702 print $fh " <th>$trans</th>\n";
704 if ($DISPLAY_CHARS ne 'NONE')
706 $trans = translate ('Number of Characters');
707 print $fh " <th>$trans</th>\n";
711 $trans = translate ('When?');
712 print $fh " <th>$trans</th>\n";
715 $trans = translate ('Random Quote');
716 print $fh " <th>$trans</th>\n",
719 @$SortedNicklist = sort
721 $NickData->{$b}{"${sort_field}_total"} <=> $NickData->{$a}{"${sort_field}_total"}
726 for (@$SortedNicklist)
729 my $ident = nick_to_ident ($nick);
730 my $name = chatter_to_name ("$nick!$ident");
731 my $print = $name || $nick;
735 # As long as we didn't hit the
736 # $LongLines-limit we continue
738 if ($linescount <= $LongLines)
740 $NicksInMainTable->{$nick} = $linescount;
742 my $quote = translate ('-- no quote available --');
744 if (@{$QuoteData->{$nick}})
746 my $num = scalar (@{$QuoteData->{$nick}});
747 my $rand = int (rand ($num));
749 $quote = html_escape ($QuoteData->{$nick}[$rand][1]);
757 $link = get_link ($name);
758 $image = get_image ($name);
759 $realname = get_realname ($name);
763 qq# <td class="numeration"># . $linescount . "</td>\n";
767 if ($DEFAULT_IMAGE and !$image)
769 $image = $DEFAULT_IMAGE;
772 print $fh qq# <td class="image">#;
777 print $fh qq#<a href="$link">#;
779 print $fh qq#<img src="$image" alt="$name" />#;
792 my $title = $realname;
795 $title = "User: $name; " if ($name);
796 $title .= "Ident: $ident";
798 print $fh qq# <td class="nick" title="$title">#;
802 print $fh qq#<a href="$link">$print</a></td>\n#
806 print $fh qq#$print</td>\n#;
809 if ($DISPLAY_LINES ne 'NONE')
811 print $fh qq# <td class="bar">#;
812 if (($DISPLAY_LINES eq 'BOTH') or ($DISPLAY_LINES eq 'BAR'))
814 my $code = bar ($max_lines, $NickData->{$nick}{'lines'});
817 print $fh ' ' if ($DISPLAY_LINES eq 'BOTH');
818 if (($DISPLAY_LINES eq 'BOTH') or ($DISPLAY_LINES eq 'NUMBER'))
820 print $fh $NickData->{$nick}{'lines_total'};
825 if ($DISPLAY_WORDS ne 'NONE')
827 print $fh qq# <td class="bar">#;
828 if (($DISPLAY_WORDS eq 'BOTH') or ($DISPLAY_WORDS eq 'BAR'))
830 my $code = bar ($max_words, $NickData->{$nick}{'words'});
833 print $fh ' ' if ($DISPLAY_WORDS eq 'BOTH');
834 if (($DISPLAY_WORDS eq 'BOTH') or ($DISPLAY_WORDS eq 'NUMBER'))
836 print $fh $NickData->{$nick}{'words_total'};
841 if ($DISPLAY_CHARS ne 'NONE')
843 print $fh qq# <td class="bar">#;
844 if (($DISPLAY_CHARS eq 'BOTH') or ($DISPLAY_CHARS eq 'BAR'))
846 my $code = bar ($max_chars, $NickData->{$nick}{'chars'});
849 print $fh ' ' if ($DISPLAY_CHARS eq 'BOTH');
850 if (($DISPLAY_CHARS eq 'BOTH') or ($DISPLAY_CHARS eq 'NUMBER'))
852 print $fh $NickData->{$nick}{'chars_total'};
859 my $code = bar ($NickData->{$nick}{'chars_total'}, $NickData->{$nick}{'chars'});
860 print $fh qq# <td class="bar">$code</td>\n#;
863 print $fh qq# <td class="quote">$quote</td>\n#,
866 if ($linescount == $LongLines)
868 print $fh "</table>\n\n";
872 # Ok, we have too many people to
873 # list them all so we start a
874 # smaller table and just list the
875 # names.. (Six names per line..)
876 elsif ($linescount <= ($LongLines + 6 * $ShortLines))
878 my $row_in_this_table = int (($linescount - $LongLines - 1) / 6);
879 my $col_in_this_table = ($linescount - $LongLines - 1) % 6;
882 if ($SORT_BY eq 'LINES')
884 $total = $NickData->{$nick}{'lines_total'};
886 elsif ($SORT_BY eq 'WORDS')
888 $total = $NickData->{$nick}{'words_total'};
890 else # ($SORT_BY eq 'CHARS')
892 $total = $NickData->{$nick}{'chars_total'};
895 my $title = $name ? get_realname ($name) : '';
898 $title = "User: $name; " if ($name);
899 $title .= "Ident: $ident";
902 if ($row_in_this_table == 0 and $col_in_this_table == 0)
904 $trans = translate ("They didn't write so much");
905 print $fh "<h2>$trans</h2>\n",
906 qq#<table class="small_ranking">\n#,
910 if ($col_in_this_table == 0 and $row_in_this_table != 0)
912 print $fh " </tr>\n",
916 print $fh qq# <td title="$title">$print ($total)</td>\n#;
918 if ($row_in_this_table == $ShortLines and $col_in_this_table == 5)
920 print $fh " </tr>\n",
925 # There is no else. There are
926 # just too many people around.
927 # I might add a "There are xyz
928 # unmentioned nicks"-line..
931 if (($linescount > $LongLines)
932 and ($linescount <= ($LongLines + 6 * $ShortLines)))
934 my $col = ($linescount - $LongLines - 1) % 6;
938 print $fh qq# <td> </td>\n#;
942 print $fh " </tr>\n";
945 if ($linescount != $LongLines)
947 print $fh "</table>\n\n";
951 # this is called by "&ranking ();" and prints the horizontal usage-bar in the
952 # detailed nick-table
958 confess () unless (ref ($source) eq 'ARRAY');
960 # BAR_WIDTH is a least 10
961 my $max_width = $BAR_WIDTH - 4;
968 if (!$max_num) { return ($retval); }
969 $factor = $max_width / $max_num;
971 for ($i = 0; $i < 4; $i++)
975 my $img = $H_IMAGES[$i];
977 for ($j = 0; $j < 6; $j++)
979 my $hour = ($i * 6) + $j;
980 $sum += $source->[$hour];
983 $width += int (0.5 + ($sum * $factor));
985 $retval .= qq#<img src="$img" style="width: # . $width . q#px"#;
986 if ($i == 0) { $retval .= qq# class="first"#; }
987 elsif ($i == 3) { $retval .= qq# class="last"#; }
988 $retval .= qq( alt="$sum" />);
994 =head1 EXPORTED FUNCTIONS
998 =item B<get_core_nick_counters> (I<$nick>)
1000 Returns a hash-ref that containes all the nick-counters available. It looks
1004 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)],
1005 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)],
1006 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)],
1014 sub get_core_nick_counters
1018 if (!defined ($NickData->{$nick}))
1023 return ($NickData->{$nick});
1026 =item B<get_sorted_nicklist> ()
1028 Returns an array-ref that containes all nicks, sorted by the field given in the
1033 sub get_sorted_nicklist
1035 return ($SortedNicklist);
1038 =item B<nick_is_in_main_table> (I<$nick>)
1040 Returns the position of the nick in the main table or zero if it is not in the
1045 sub nick_is_in_main_table
1049 return (defined ($NicksInMainTable->{$nick}) ? $NicksInMainTable->{$nick} : 0);
1056 Florian octo Forster E<lt>octo at verplant.orgE<gt>