Просмотр исходного кода

The "Christoph got bored in Ireland" changes:
* Get channel music charts with ShowCharts and ChartsHistory (suggested by
Sven in SF tracker #1164596).
* Made ShowLastSeen=1 and ShowMostActiveByHourGraph=1 default.
* More verbose config parser error messages.
* Most active nicks timebars have mouse-over titles.
* Update copyright years and add copyright and license to documentation.

Christoph Berg 21 лет назад
Родитель
Сommit
4beba8be97
9 измененных файлов с 292 добавлено и 69 удалено
  1. 2 1
      docs/CREDITS
  2. 10 2
      docs/Changelog
  3. 136 3
      docs/pisg-doc.xml
  4. 11 4
      lang.txt
  5. 13 8
      modules/Pisg.pm
  6. 21 3
      modules/Pisg/Common.pm
  7. 64 38
      modules/Pisg/HTMLGenerator.pm
  8. 33 9
      modules/Pisg/Parser/Logfile.pm
  9. 2 1
      pisg

+ 2 - 1
docs/CREDITS

@@ -13,7 +13,8 @@ Major contributors:
  * Christoph Berg <cb@df7cb.de>
  * Christoph Berg <cb@df7cb.de>
    | NFiles and UserPics options, wildcards for random user pictures,
    | NFiles and UserPics options, wildcards for random user pictures,
      wildcard and regexp support for IgnoreWords, FoulWords, ViolentWords,
      wildcard and regexp support for IgnoreWords, FoulWords, ViolentWords,
-     charset conversion support, BigNumbersThreshold option, karma ...
+     charset conversion support, BigNumbersThreshold option, karma, music
+     charts ...
 
 
 Other contributors:
 Other contributors:
 
 

+ 10 - 2
docs/Changelog

@@ -4,8 +4,16 @@ pisg (0.65) - ??
      though (thanks to Nico for the test log).
      though (thanks to Nico for the test log).
    * Fixed breakage when multiple LogDirs were given (thanks to Toni Viemerö
    * Fixed breakage when multiple LogDirs were given (thanks to Toni Viemerö
      for the report, SF tracker #1155433).
      for the report, SF tracker #1155433).
-   * Updated translations:
-      + French (thanks, Sébastien Bourgeois)
+   The "Christoph got bored in Ireland" changes:
+   * Get channel music charts with ShowCharts and ChartsHistory (suggested by
+     Sven in SF tracker #1164596).
+   * Made ShowLastSeen=1 and ShowMostActiveByHourGraph=1 default.
+   * More verbose config parser error messages.
+   * Most active nicks timebars have mouse-over titles.
+   * Update copyright years and add copyright and license to documentation.
+   Updated translations:
+   * French (thanks, Sébastien Bourgeois).
+   * Finnish (thanks, Sami Karuaho).
 
 
 pisg (0.64) - Thu Feb, 24th 2005
 pisg (0.64) - Thu Feb, 24th 2005
    Morten:
    Morten:

+ 136 - 3
docs/pisg-doc.xml

@@ -1361,7 +1361,7 @@
     </refsect1>
     </refsect1>
     <refsect1>
     <refsect1>
     <title>Default</title>
     <title>Default</title>
-    <para> 0 (disabled) </para>
+    <para> 1 (enabled) </para>
     </refsect1>
     </refsect1>
     </refentry>
     </refentry>
 
 
@@ -1866,6 +1866,42 @@
     </refsect1>
     </refsect1>
     </refentry>
     </refentry>
 
 
+    <!-- *** SHOWCHARTS *** -->
+    <refentry id="ShowCharts">
+
+    <refmeta> <refentrytitle>ShowCharts</refentrytitle> </refmeta>
+
+    <refnamediv>
+    <refname>ShowCharts</refname>
+    <refpurpose>enable or disable channel music charts</refpurpose>
+    </refnamediv>
+
+    <refsynopsisdiv><programlisting>
+      <![CDATA[
+        <channel="#channel">
+         Logfile = "channel.log"
+         Format = "xchat"
+         ShowCharts = "0"
+        </channel>
+
+        <set ShowCharts="1">
+      ]]>
+    </programlisting></refsynopsisdiv>
+
+    <refsect1>
+    <title>Description</title>
+    <para>
+    With this option set, pisg creates a chart listing of the top songs played
+    on the channel. See also <xref linkend="ChartsHistory" /> and
+    <xref linkend="ChartsRegexp" />.
+    </para>
+    </refsect1>
+    <refsect1>
+    <title>Default</title>
+    <para> 0 (disabled) </para>
+    </refsect1>
+    </refentry>
+
     <!-- *** SHOWOPS *** -->
     <!-- *** SHOWOPS *** -->
     <refentry id="ShowOps">
     <refentry id="ShowOps">
 
 
@@ -2197,7 +2233,7 @@
     </refsect1>
     </refsect1>
     <refsect1>
     <refsect1>
     <title>Default</title>
     <title>Default</title>
-    <para> 0 (disabled) </para>
+    <para> 1 (enabled) </para>
     </refsect1>
     </refsect1>
     </refentry>
     </refentry>
 
 
@@ -2758,6 +2794,76 @@
     </refsect1>
     </refsect1>
     </refentry>
     </refentry>
 
 
+    <!-- *** CHARTSHISTORY *** -->
+    <refentry id="ChartsHistory">
+
+    <refmeta> <refentrytitle>ChartsHistory</refentrytitle> </refmeta>
+
+    <refnamediv>
+    <refname>ChartsHistory</refname>
+    <refpurpose>number of songs to show</refpurpose>
+    </refnamediv>
+
+    <refsynopsisdiv><programlisting>
+      <![CDATA[
+        <channel="#channel">
+         Logfile = "channel.log"
+         Format = "mIRC"
+         ChartsHistory = "10"
+        </channel>
+
+        <set ChartsHistory="5">
+      ]]>
+    </programlisting></refsynopsisdiv>
+
+    <refsect1>
+    <title>Description</title>
+    <para>
+    This option sets the number of songs that will be show in the channel music
+    charts. See also <xref linkend="ShowCharts" /> and
+    <xref linkend="ChartsRegexp" />.
+    </para>
+    </refsect1>
+    <refsect1>
+    <title>Default</title>
+    <para> 5 (the Top Five) </para>
+    </refsect1>
+    </refentry>
+
+    <!-- *** CHARTSREGEXP *** -->
+    <refentry id="ChartsRegexp">
+
+    <refmeta> <refentrytitle>ChartsRegexp</refentrytitle> </refmeta>
+
+    <refnamediv>
+    <refname>ChartsRegexp</refname>
+    <refpurpose>how to recognize songs played</refpurpose>
+    </refnamediv>
+
+    <refsynopsisdiv><programlisting>
+      <![CDATA[
+        <channel="#channel">
+         Logfile = "channel.log"
+         Format = "mIRC"
+         ChartsRegexp = "(?:np:|np - |playing )\s*"
+        </channel>
+      ]]>
+    </programlisting></refsynopsisdiv>
+
+    <refsect1>
+    <title>Description</title>
+    <para>
+    This option is a perl regexp that is used to recognize songs played. Please
+    tell the pisg mailing list if you have a better default. See also
+    <xref linkend="ShowCharts" /> and <xref linkend="ChartsHistory" />.
+    </para>
+    </refsect1>
+    <refsect1>
+    <title>Default</title>
+    <para> "(?:np:|np - |playing )\s*" </para>
+    </refsect1>
+    </refentry>
+
     <!-- *** WORDHISTORY *** -->
     <!-- *** WORDHISTORY *** -->
     <refentry id="WordHistory">
     <refentry id="WordHistory">
 
 
@@ -3542,6 +3648,33 @@
     <para> Logfile </para>
     <para> Logfile </para>
     </refsect1>
     </refsect1>
     </refentry>
     </refentry>
-</chapter>
+
+    </chapter>
+
+    <chapter id="copyright">
+    <title>Copyright and License</title>
+
+    <para>
+    pisg - Perl IRC Statistics Generator
+
+    Copyright (C) 2001-2005  Morten Brix Pedersen - &lt;morten at wtf.dk&gt;
+
+    Copyright (C) 2003-2005  Christoph Berg &lt;cb at df7cb.de&gt;
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+    </para>
+    </chapter>
 
 
 </book>
 </book>

+ 11 - 4
lang.txt

@@ -20,7 +20,7 @@
 # (NL) Dutch - Jeroen van Nimwegen <jeroen.van.nimwegen@gmail.com> (2005-02-17)
 # (NL) Dutch - Jeroen van Nimwegen <jeroen.van.nimwegen@gmail.com> (2005-02-17)
 # (SE) Swedish - Andreas Henriksson <andreas@fjortis.info> (2005-01-12)
 # (SE) Swedish - Andreas Henriksson <andreas@fjortis.info> (2005-01-12)
 # (FI) Finnish - Kirler@paincreators <kirler@paincreators.net>
 # (FI) Finnish - Kirler@paincreators <kirler@paincreators.net>
-#      last update: 2005-01-12 by Sami Karuaho <sami.karuaho@kanetti.fi>
+#      last update: Sami Karuaho <sami.karuaho@kanetti.fi>( 2005-03-19)
 # (SI) Slovenian - Ales Tepina <??> (2005-01-09: bounces)
 # (SI) Slovenian - Ales Tepina <??> (2005-01-09: bounces)
 # (HU) Hungarian - Gyuri Horak <??> (2005-01-09: bounces)
 # (HU) Hungarian - Gyuri Horak <??> (2005-01-09: bounces)
 # (EE) Estonian - Hannes Tarien <comcute@users.sf.net>
 # (EE) Estonian - Hannes Tarien <comcute@users.sf.net>
@@ -148,6 +148,7 @@ mostwordstopic = "Most used words"
 referencetopic = "Most referenced nicks"
 referencetopic = "Most referenced nicks"
 karmatopic = "[:channel] karma"
 karmatopic = "[:channel] karma"
 urlstopic = "Most referenced URLs"
 urlstopic = "Most referenced URLs"
+chartstopic = "[:channel] Music Charts"
 notopic = "A topic was never set on this channel."
 notopic = "A topic was never set on this channel."
 mostnickstopic = "Users with most nicknames"
 mostnickstopic = "Users with most nicknames"
 bylinetopic = "[:date] on [:time] by [:nick]"
 bylinetopic = "[:date] on [:time] by [:nick]"
@@ -196,6 +197,9 @@ gender = "Gender"
 gender_f = "Female"
 gender_f = "Female"
 gender_m = "Male"
 gender_m = "Male"
 gender_b = "Bot"
 gender_b = "Bot"
+song = "Song"
+numberplayed = "How Often Played"
+playedby = "Last Played by"
 
 
 # Mouse-over titles
 # Mouse-over titles
 pisghomepage = "Go to the pisg homepage"
 pisghomepage = "Go to the pisg homepage"
@@ -312,6 +316,7 @@ mostwordstopic = "Am meisten benutzte W
 referencetopic = "Begehrte Nicks :)"
 referencetopic = "Begehrte Nicks :)"
 karmatopic = "[:channel]-Karma"
 karmatopic = "[:channel]-Karma"
 urlstopic = "Am meisten benutzte URLs"
 urlstopic = "Am meisten benutzte URLs"
+chartstopic = "Ohrwürmer auf [:channel]"
 notopic = "In diesem Channel wurde kein Topic gesetzt."
 notopic = "In diesem Channel wurde kein Topic gesetzt."
 bylinetopic = "[:date] um [:time] von [:nick]"
 bylinetopic = "[:date] um [:time] von [:nick]"
 dailyactivitytopic = "Tägliche Aktivität (letzte [:n] Tage)"
 dailyactivitytopic = "Tägliche Aktivität (letzte [:n] Tage)"
@@ -360,6 +365,9 @@ gender = "Geschlecht"
 gender_f = "Weiblich"
 gender_f = "Weiblich"
 gender_m = "Männlich"
 gender_m = "Männlich"
 gender_b = "Bot"
 gender_b = "Bot"
+song = "Song"
+numberplayed = "Wie oft gespielt"
+playedby = "Zuletzt gespielt von"
 
 
 # Mouse-over titles
 # Mouse-over titles
 pisghomepage = "pisg-Homepage öffnen"
 pisghomepage = "pisg-Homepage öffnen"
@@ -1666,7 +1674,7 @@ mostdeop2 = "Sijaispomoksi pyrkii <b>[:nick]</b>: n
 mostdeop3 = "Huh huh! [:channel] ei tällä kertaa rankaissut ketään!"
 mostdeop3 = "Huh huh! [:channel] ei tällä kertaa rankaissut ketään!"
 
 
 mostvoice1 = "<b>[:nick]</b> antoi voiceja (+v) [:voices]:lle henkilölle"
 mostvoice1 = "<b>[:nick]</b> antoi voiceja (+v) [:voices]:lle henkilölle"
-mostvoice2 = "Myös <b>[:nick]</b> voicetti ahkeraan: [:voices] kertaa!"
+mostvoice2 = "Myös <b>[:nick]</b> voicetti ahkerasti: [:voices] kertaa!"
 mostvoice3 = "Tällä kertaa [:channel]:n voicet on kiven alla..."
 mostvoice3 = "Tällä kertaa [:channel]:n voicet on kiven alla..."
 
 
 mostdevoice1 = "<b>[:nick]</b> riisti irkkaajilta voiceja [:devoices]:sti!"
 mostdevoice1 = "<b>[:nick]</b> riisti irkkaajilta voiceja [:devoices]:sti!"
@@ -1787,7 +1795,7 @@ show_wpl = "Sanaa lauseessa"
 show_cpl = "Merkkiä lauseessa"
 show_cpl = "Merkkiä lauseessa"
 show_lastseen = " Nähty viimeksi"
 show_lastseen = " Nähty viimeksi"
 lastused = "Viimeksi maininnut"
 lastused = "Viimeksi maininnut"
-lastseen1 = "[:days] päivä sitten" 
+lastseen1 = "Eilen" 
 lastseen2 = "[:days] päivää sitten"
 lastseen2 = "[:days] päivää sitten"
 today = "Tänään"
 today = "Tänään"
 karma = "Karma"
 karma = "Karma"
@@ -1957,7 +1965,6 @@ pisghomepage = "Pojdi na domaco stran programa pisg"
 authorhomepage = "Pojdi na avtorjevo domaco stran"
 authorhomepage = "Pojdi na avtorjevo domaco stran"
 newwindow = "Odpri v novem oknu:"
 newwindow = "Odpri v novem oknu:"
 mailto = "Poslji mail na:"
 mailto = "Poslji mail na:"
-
 </lang>
 </lang>
 
 
 ### Hungarian (Magyar lengvidzsu szovegek)
 ### Hungarian (Magyar lengvidzsu szovegek)

+ 13 - 8
modules/Pisg.pm

@@ -2,7 +2,8 @@ package Pisg;
 
 
 # Documentation(POD) for this module is found at the end of the file.
 # Documentation(POD) for this module is found at the end of the file.
 
 
-# Copyright (C) 2001-2002  <Morten Brix Pedersen> - morten@wtf.dk
+# Copyright (C) 2001-2005  <Morten Brix Pedersen> - morten@wtf.dk
+# Copyright (C) 2003-2005  Christoph Berg <cb@df7cb.de>
 #
 #
 # This program is free software; you can redistribute it and/or modify
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # it under the terms of the GNU General Public License as published by
@@ -143,7 +144,7 @@ sub get_default_config_settings
         showwords => 0,
         showwords => 0,
         showwpl => 0,
         showwpl => 0,
         showcpl => 0,
         showcpl => 0,
-        showlastseen => 0,
+        showlastseen => 1,
         showlegend => 1,
         showlegend => 1,
         showkickline => 1,
         showkickline => 1,
         showactionline => 1,
         showactionline => 1,
@@ -156,13 +157,14 @@ sub get_default_config_settings
         showmrn => 1,
         showmrn => 1,
         showkarma => 0,
         showkarma => 0,
         showmru => 1,
         showmru => 1,
+        showcharts => 0,
         showops => 1,
         showops => 1,
         showvoices => 0,
         showvoices => 0,
         showhalfops => 0,
         showhalfops => 0,
         showmostnicks => 0,
         showmostnicks => 0,
         showactivegenders => 0,
         showactivegenders => 0,
         showmostactivebyhour => 0,
         showmostactivebyhour => 0,
-        showmostactivebyhourgraph => 0,
+        showmostactivebyhourgraph => 1,
         showonlytop => 0,
         showonlytop => 0,
 
 
         # Less important things
         # Less important things
@@ -173,11 +175,13 @@ sub get_default_config_settings
         quotewidth => 80,
         quotewidth => 80,
         bignumbersthreshold => 'sqrt',
         bignumbersthreshold => 'sqrt',
         wordlength => 5,
         wordlength => 5,
+        dailyactivity => 0,
         activenicks => 25,
         activenicks => 25,
         activenicks2 => 30,
         activenicks2 => 30,
         activenicksbyhour => 10,
         activenicksbyhour => 10,
         topichistory => 3,
         topichistory => 3,
         urlhistory => 5,
         urlhistory => 5,
+        chartshistory => 5,
         nickhistory => 5,
         nickhistory => 5,
         karmahistory => 5,
         karmahistory => 5,
         wordhistory => 10,
         wordhistory => 10,
@@ -196,6 +200,7 @@ sub get_default_config_settings
 
 
         foulwords => 'ass fuck bitch shit scheisse scheiße kacke arsch ficker ficken schlampe',
         foulwords => 'ass fuck bitch shit scheisse scheiße kacke arsch ficker ficken schlampe',
         violentwords => 'slaps beats smacks',
         violentwords => 'slaps beats smacks',
+        chartsregexp => '(?:np:|(?:now )?playing:? (?:MPEG stream from)?)\s*(.*)',
         ignorewords => '',
         ignorewords => '',
         noignoredquotes => 0,
         noignoredquotes => 0,
         tablewidth => 574,
         tablewidth => 574,
@@ -203,7 +208,6 @@ sub get_default_config_settings
 
 
         botnicks => '',            # Needed for DCpp format (non-irc)
         botnicks => '',            # Needed for DCpp format (non-irc)
 
 
-        dailyactivity => 0,
         version => "0.64",
         version => "0.64",
     };
     };
 
 
@@ -237,7 +241,8 @@ sub get_language_templates
                 last if ($_ =~ /<\/lang>/i);
                 last if ($_ =~ /<\/lang>/i);
 
 
                 # Get 'template = "Text"' in language file:
                 # Get 'template = "Text"' in language file:
-                if ($_ =~ /(\w+)\s+=\s+"(.*)"\s*$/) {
+                if ($_ =~ /^(\w+)\s*=\s*"(.*)"\s*$/) {
+                    warn "duplicate translation $1 -> $2" if $self->{tmps}->{$current_lang}{$1};
                     $self->{tmps}->{$current_lang}{$1} = $2;
                     $self->{tmps}->{$current_lang}{$1} = $2;
                 }
                 }
             }
             }
@@ -361,7 +366,7 @@ sub init_config
 
 
                     }
                     }
                 } elsif ($_ !~ /^$/) {
                 } elsif ($_ !~ /^$/) {
-                    print STDERR "Warning: $self->{cfg}->{configfile}, line $.: Unrecognized line\n";
+                    print STDERR "Warning: $self->{cfg}->{configfile}, line $.: Unrecognized line: $_";
                 }
                 }
             }
             }
         } elsif ($line =~ /<include\s*=\s*(["'])(.+?)\1\s*>/) {
         } elsif ($line =~ /<include\s*=\s*(["'])(.+?)\1\s*>/) {
@@ -382,7 +387,7 @@ sub init_config
             print STDERR "Warning: $self->{cfg}->{configfile}, line $.: Missing end on element <$1 (probably multi-line?)\n";
             print STDERR "Warning: $self->{cfg}->{configfile}, line $.: Missing end on element <$1 (probably multi-line?)\n";
         } elsif ($line =~ /\S/) {
         } elsif ($line =~ /\S/) {
             $line =~ s/\n//;
             $line =~ s/\n//;
-            print STDERR "Warning: $self->{cfg}->{configfile}, line $.: Unrecognized line\n";
+            print STDERR "Warning: $self->{cfg}->{configfile}, line $.: Unrecognized line: $line\n";
         }
         }
     }
     }
 
 
@@ -467,7 +472,7 @@ _END
         }
         }
 
 
         my $stats = $analyzer->analyze();
         my $stats = $analyzer->analyze();
-        $self->{cfg}->{analyzer} = $analyzer;
+        $self->{cfg}->{analyzer} = $analyzer; # we need the parser in _format_line
 
 
         # Initialize HTMLGenerator object
         # Initialize HTMLGenerator object
         my $generator;
         my $generator;

+ 21 - 3
modules/Pisg/Common.pm

@@ -1,5 +1,24 @@
 package Pisg::Common;
 package Pisg::Common;
 
 
+# pisg - Perl IRC Statistics Generator
+#
+# Copyright (C) 2001-2005  <Morten Brix Pedersen> - morten@wtf.dk
+# Copyright (C) 2003-2005  Christoph Berg <cb@df7cb.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
 =head1 NAME
 =head1 NAME
 
 
 Pisg::Common - some common functions of pisg.
 Pisg::Common - some common functions of pisg.
@@ -191,13 +210,12 @@ sub urlencode
 
 
 sub randomglob
 sub randomglob
 {
 {
-    my $pattern = shift;
-    my $globpath = shift;
+    my ($pattern, $globpath, $nick) = @_;
     return $pattern unless $pattern =~ /[*?]/;
     return $pattern unless $pattern =~ /[*?]/;
     my @globs = glob $globpath . $pattern;
     my @globs = glob $globpath . $pattern;
     my $return = $globs[int(rand(@globs))];
     my $return = $globs[int(rand(@globs))];
     unless($return) {
     unless($return) {
-        print STDERR "Warning: no picture for $pattern found in $globpath\n";
+        print STDERR "Warning: picture $globpath$pattern for $nick not found\n";
         return $pattern;
         return $pattern;
     }
     }
     $return =~ s/^$globpath//;
     $return =~ s/^$globpath//;

+ 64 - 38
modules/Pisg/HTMLGenerator.pm

@@ -149,6 +149,10 @@ sub create_output
         $self->_mosturls();
         $self->_mosturls();
     }
     }
 
 
+    if ($self->{cfg}->{showcharts}) {
+        $self->_charts();
+    }
+
     if ($self->{cfg}->{showbignumbers}) {
     if ($self->{cfg}->{showbignumbers}) {
         $self->_headline($self->_template_text('othernumtopic'));
         $self->_headline($self->_template_text('othernumtopic'));
         _html("<table width=\"$self->{cfg}->{tablewidth}\">\n"); # Needed for sections
         _html("<table width=\"$self->{cfg}->{tablewidth}\">\n"); # Needed for sections
@@ -439,7 +443,7 @@ sub _activetimes
     # The most actives times on the channel
     # The most actives times on the channel
     my $self = shift;
     my $self = shift;
 
 
-    my (%output, $class);
+    my (%output);
 
 
     $self->_headline($self->_template_text('activetimestopic'));
     $self->_headline($self->_template_text('activetimestopic'));
 
 
@@ -447,27 +451,17 @@ sub _activetimes
 
 
     my $highest_value = $self->{stats}->{times}{$toptime[0]};
     my $highest_value = $self->{stats}->{times}{$toptime[0]};
 
 
-    my @now = localtime($self->{cfg}->{timestamp});
-
-    my $image;
-
     for my $hour (sort keys %{ $self->{stats}->{times} }) {
     for my $hour (sort keys %{ $self->{stats}->{times} }) {
 
 
         my $size = int(($self->{stats}->{times}{$hour} / $highest_value) * 100);
         my $size = int(($self->{stats}->{times}{$hour} / $highest_value) * 100);
         my $percent = ($self->{stats}->{times}{$hour} / $self->{stats}->{parsedlines}) * 100;
         my $percent = ($self->{stats}->{times}{$hour} / $self->{stats}->{parsedlines}) * 100;
-        my $lines_per_hour = $self->{stats}->{times}{$hour};
         $percent =~ s/(\.\d)\d+/$1/;
         $percent =~ s/(\.\d)\d+/$1/;
+        my $lines_per_hour = $self->{stats}->{times}{$hour};
 
 
-        if ($size < 1) {
-            # Opera doesn't understand '0.xxxx' in the height="xx" attr,
-            # so we simply round up to 1 here.
-            $size = 1;
-        }
-
-        $image = "pic_v_".(int($hour/6)*6);
+        my $image = "pic_v_".(int($hour/6)*6);
         $image = $self->{cfg}->{$image};
         $image = $self->{cfg}->{$image};
 
 
-        $output{$hour} = "<td align=\"center\" valign=\"bottom\" class=\"asmall\">$percent%<br /><img src=\"$self->{cfg}->{piclocation}/$image\" width=\"15\" height=\"$size\" alt=\"$lines_per_hour\" title=\"$lines_per_hour\"/></td>\n";
+        $output{$hour} = "<td align=\"center\" valign=\"bottom\" class=\"asmall\">$percent%<br /><img src=\"$self->{cfg}->{piclocation}/$image\" width=\"15\" height=\"$size\" alt=\"$lines_per_hour\" title=\"$lines_per_hour\"/></td>\n" if $size;
     }
     }
 
 
     _html("<table border=\"0\"><tr>\n");
     _html("<table border=\"0\"><tr>\n");
@@ -475,7 +469,7 @@ sub _activetimes
     for ($b = 0; $b < 24; $b++) {
     for ($b = 0; $b < 24; $b++) {
         $a = sprintf("%02d", $b);
         $a = sprintf("%02d", $b);
 
 
-        if (!defined($output{$a}) || $output{$a} eq "") {
+        if (!defined($output{$a})) {
             _html("<td align=\"center\" valign=\"bottom\" class=\"asmall\">0%</td>");
             _html("<td align=\"center\" valign=\"bottom\" class=\"asmall\">0%</td>");
         } else {
         } else {
             _html($output{$a});
             _html($output{$a});
@@ -485,17 +479,13 @@ sub _activetimes
     _html("</tr><tr>");
     _html("</tr><tr>");
 
 
     # Remove leading zero
     # Remove leading zero
-    $toptime[0] =~ s/0(\d)/$1/;
+    $toptime[0] =~ s/^0//;
 
 
     for ($b = 0; $b < 24; $b++) {
     for ($b = 0; $b < 24; $b++) {
-        if ($toptime[0] == $b) {
-            # Highlight the top time
-            $class = 'hirankc10center';
-        } else {
-            $class = 'rankc10center';
-        }
+        # Highlight the top time
+        my $class = $toptime[0] == $b ? 'hirankc10center' : 'rankc10center';
         _html("<td class=\"$class\" align=\"center\">$b</td>");
         _html("<td class=\"$class\" align=\"center\">$b</td>");
-}
+    }
 
 
     _html("</tr></table>");
     _html("</tr></table>");
 
 
@@ -1961,12 +1951,7 @@ sub _mosturls
             }
             }
             $printurl = htmlentities($printurl, $self->{cfg}->{charset});
             $printurl = htmlentities($printurl, $self->{cfg}->{charset});
             my $linkurl = urlencode($sorturls[$i]);
             my $linkurl = urlencode($sorturls[$i]);
-            my $class;
-            if ($a == 1) {
-                $class = 'hirankc';
-            } else {
-                $class = 'rankc';
-            }
+            my $class = ($a == 1) ? 'hirankc' : 'rankc';
             _html("<tr><td class=\"$class\">$a</td>");
             _html("<tr><td class=\"$class\">$a</td>");
             _html("<td class=\"hicell\"><a href=\"$linkurl\">$printurl</a></td>");
             _html("<td class=\"hicell\"><a href=\"$linkurl\">$printurl</a></td>");
             _html("<td class=\"hicell\">$urlcount</td>");
             _html("<td class=\"hicell\">$urlcount</td>");
@@ -1977,6 +1962,43 @@ sub _mosturls
     }
     }
 }
 }
 
 
+sub _charts
+{
+    # List showing the most played songs
+    my $self = shift;
+
+    my @sortcharts = sort { $self->{stats}->{chartcounts}{$b} <=> $self->{stats}->{chartcounts}{$a} }
+                        keys %{ $self->{stats}->{chartcounts} };
+
+    if (@sortcharts) {
+
+        $self->_headline($self->_template_text('chartstopic'));
+
+        _html("<table border=\"0\" width=\"$self->{cfg}->{tablewidth}\"><tr>");
+        _html("<td>&nbsp;</td><td class=\"tdtop\"><b>" . $self->_template_text('song') . "</b></td>");
+        _html("<td class=\"tdtop\"><b>" . $self->_template_text('numberplayed') . "</b></td>");
+        _html("<td class=\"tdtop\"><b>" . $self->_template_text('playedby') . "</b></td></tr>");
+
+        for(my $i = 0; $i < $self->{cfg}->{chartshistory}; $i++) {
+            last unless $i < @sortcharts;
+            my $a = $i + 1;
+            my $song = $sortcharts[$i];
+            my $chartcount = $self->{stats}->{chartcounts}{$song};
+            my $lastused = $self->{stats}->{chartnicks}{$song};
+            $song = $self->{stats}->{word_upcase}{$song};
+            $song = substr($song, 0, 60) if (length($song) > 60);
+            $song = $self->_format_word($song);
+            my $class = ($a == 1) ? 'hirankc' : 'rankc';
+            _html("<tr><td class=\"$class\">$a</td>");
+            _html("<td class=\"hicell\">$song</td>");
+            _html("<td class=\"hicell\">$chartcount</td>");
+            _html("<td class=\"hicell\">$lastused</td>");
+            _html("</tr>");
+        }
+        _html("</table>");
+    }
+}
+
 sub _legend
 sub _legend
 {
 {
     # A legend showing the timebars and their associated time.
     # A legend showing the timebars and their associated time.
@@ -2047,11 +2069,12 @@ sub _user_linetimes
     my $len      = ($self->{stats}->{lines}{$nick} / $self->{stats}->{lines}{$top}) * 100;
     my $len      = ($self->{stats}->{lines}{$nick} / $self->{stats}->{lines}{$top}) * 100;
 
 
     for (my $i = 0; $i <= 3; $i++) {
     for (my $i = 0; $i <= 3; $i++) {
-        next if not defined $self->{stats}->{line_times}{$nick}[$i];
-        my $w = int(($self->{stats}->{line_times}{$nick}[$i] / $self->{stats}->{lines}{$nick}) * $len);
+        my $l = $self->{stats}->{line_times}{$nick}[$i];
+        next if not defined $l;
+        my $w = int(($l / $self->{stats}->{lines}{$nick}) * $len);
         if ($w) {
         if ($w) {
             my $pic = 'pic_h_'.(6*$i);
             my $pic = 'pic_h_'.(6*$i);
-            $bar .= "<img src=\"$self->{cfg}->{piclocation}/$self->{cfg}->{$pic}\" border=\"0\" width=\"$w\" height=\"15\" align=\"middle\" alt=\"$self->{stats}->{line_times}{$nick}[$i]\" />";
+            $bar .= "<img src=\"$self->{cfg}->{piclocation}/$self->{cfg}->{$pic}\" border=\"0\" width=\"$w\" height=\"15\" align=\"middle\" alt=\"$l\" title=\"$l\" />";
         }
         }
     }
     }
     return "$bar&nbsp;$self->{stats}->{lines}{$nick}";
     return "$bar&nbsp;$self->{stats}->{lines}{$nick}";
@@ -2089,11 +2112,12 @@ sub _user_times
     my $timestat = ($self->{cfg}->{sortbywords} ? 'word_times' : 'line_times');
     my $timestat = ($self->{cfg}->{sortbywords} ? 'word_times' : 'line_times');
     
     
     for (my $i = 0; $i <= 3; $i++) {
     for (my $i = 0; $i <= 3; $i++) {
-        next if not defined $self->{stats}->{$timestat}{$nick}[$i];
-        my $w = int(($self->{stats}->{$timestat}{$nick}[$i] / $self->{stats}->{$itemstat}{$nick}) * 40);
+        my $l = $self->{stats}->{$timestat}{$nick}[$i];
+        next if not defined $l;
+        my $w = int(($l / $self->{stats}->{$itemstat}{$nick}) * 40);
         if ($w) {
         if ($w) {
             my $pic = 'pic_h_'.(6*$i);
             my $pic = 'pic_h_'.(6*$i);
-            $bar .= "<img src=\"$self->{cfg}->{piclocation}/$self->{cfg}->{$pic}\" border=\"0\" width=\"$w\" height=\"15\" alt=\"\" />";
+            $bar .= "<img src=\"$self->{cfg}->{piclocation}/$self->{cfg}->{$pic}\" border=\"0\" width=\"$w\" height=\"15\" alt=\"$l\" title=\"$l\" />";
         }
         }
     }
     }
     return $bar;
     return $bar;
@@ -2113,13 +2137,14 @@ sub _user_pic
     my $biguserpic = $self->{users}->{biguserpics}{$nick};
     my $biguserpic = $self->{users}->{biguserpics}{$nick};
     if ($biguserpic) {
     if ($biguserpic) {
         $biguserpic = $self->{cfg}->{imagepath} .
         $biguserpic = $self->{cfg}->{imagepath} .
-            randomglob($biguserpic, $self->{cfg}->{imageglobpath})
+            randomglob($biguserpic, $self->{cfg}->{imageglobpath}, $nick)
                 if $biguserpic !~ /^http:\/\//i;
                 if $biguserpic !~ /^http:\/\//i;
         $output .= "<a href=\"$biguserpic\">";
         $output .= "<a href=\"$biguserpic\">";
     }
     }
 
 
     my $pic = $self->{users}->{userpics}{$nick} || $self->{cfg}->{defaultpic};
     my $pic = $self->{users}->{userpics}{$nick} || $self->{cfg}->{defaultpic};
-    $pic = $self->{cfg}->{imagepath} . randomglob($pic, $self->{cfg}->{imageglobpath})
+    $pic = $self->{cfg}->{imagepath} .
+        randomglob($pic, $self->{cfg}->{imageglobpath}, $nick)
         unless $pic =~ /^http:\/\//i;
         unless $pic =~ /^http:\/\//i;
     my $height = $self->{cfg}->{picheight} ? " height=\"$self->{cfg}->{picheight}\"" : "";
     my $height = $self->{cfg}->{picheight} ? " height=\"$self->{cfg}->{picheight}\"" : "";
     my $width = $self->{cfg}->{picwidth} ? " width=\"$self->{cfg}->{picwidth}\"" : "";
     my $width = $self->{cfg}->{picwidth} ? " width=\"$self->{cfg}->{picwidth}\"" : "";
@@ -2421,7 +2446,8 @@ Morten Brix Pedersen <morten@wtf.dk>
 
 
 =head1 COPYRIGHT
 =head1 COPYRIGHT
 
 
-Copyright (C) 2001-2002 Morten Brix Pedersen. All rights reserved.
+Copyright (C) 2001-2005 Morten Brix Pedersen. All rights reserved.
+Copyright (C) 2003-2005 Christoph Berg <cb@df7cb.de>.
 This program is free software; you can redistribute it and/or modify it
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GPL, license is included with the distribution of
 under the terms of the GPL, license is included with the distribution of
 this file.
 this file.

+ 33 - 9
modules/Pisg/Parser/Logfile.pm

@@ -52,6 +52,7 @@ sub new
     $self->{foulwords_regexp} = qr/($self->{cfg}->{foulwords})/i if $self->{cfg}->{foulwords};
     $self->{foulwords_regexp} = qr/($self->{cfg}->{foulwords})/i if $self->{cfg}->{foulwords};
     $self->{ignorewords_regexp} = qr/$self->{cfg}->{ignorewords}/i if $self->{cfg}->{ignorewords};
     $self->{ignorewords_regexp} = qr/$self->{cfg}->{ignorewords}/i if $self->{cfg}->{ignorewords};
     $self->{violentwords_regexp} = qr/^($self->{cfg}->{violentwords}) (\S+)(.*)/i if $self->{cfg}->{violentwords};
     $self->{violentwords_regexp} = qr/^($self->{cfg}->{violentwords}) (\S+)(.*)/i if $self->{cfg}->{violentwords};
+    $self->{chartsregexp} = qr/^$self->{cfg}->{chartsregexp}/i if $self->{cfg}->{chartsregexp};
 
 
     return $self;
     return $self;
 }
 }
@@ -351,7 +352,7 @@ sub _parse_file
 
 
                     if ($saying !~ /[a-z]/o && $saying =~ /[A-Z]/o) {
                     if ($saying !~ /[a-z]/o && $saying =~ /[A-Z]/o) {
                         # Ignore single smileys on a line. eg. '<user> :P'
                         # Ignore single smileys on a line. eg. '<user> :P'
-                        if ($saying !~ /^[8;:=][ ^-o]?[)pPD}\]>]$/o) {
+                        if ($saying !~ /^[8;:=][ ^-o]?[)pPD\}\]>]$/o) {
                             $stats->{allcaps}{$nick}++;
                             $stats->{allcaps}{$nick}++;
                             push @{ $lines->{allcaplines}{$nick} }, $line;
                             push @{ $lines->{allcaplines}{$nick} }, $line;
                         }
                         }
@@ -362,13 +363,12 @@ sub _parse_file
                         push @{ $lines->{foullines}{$nick} }, $line;
                         push @{ $lines->{foullines}{$nick} }, $line;
                     }
                     }
 
 
-
                     # Who smiles the most?
                     # Who smiles the most?
                     # A regex matching al lot of smilies
                     # A regex matching al lot of smilies
                     $stats->{smiles}{$nick}++
                     $stats->{smiles}{$nick}++
-                        if ($saying =~ /[8;:=][ ^-o]?[)pPD}\]>]/o);
+                        if ($saying =~ /[8;:=][ ^-o]?[)pPD\}\]>]/o);
 
 
-                    if ($saying =~ /[8;:=][ ^-]?[\(\[\\\/{]/o and
+                    if ($saying =~ /[8;:=][ ^-]?[\(\[\\\/\{]/o and
                         $saying !~ /\w+:\/\//o) {
                         $saying !~ /\w+:\/\//o) {
                         $stats->{frowns}{$nick}++;
                         $stats->{frowns}{$nick}++;
                     }
                     }
@@ -393,14 +393,28 @@ sub _parse_file
                         }
                         }
                     }
                     }
 
 
+                    if ($self->{cfg}->{showcharts}) {
+                        if ($saying =~ /$self->{chartsregexp}/i) {
+                            my $Song = $1;
+                            $Song =~ s/_/ /g;
+                            $Song =~ s/\d+ ?- ?//;
+                            $Song =~ s/\.mp3//g;
+                            $Song =~ s/ \.\.\.$//;
+                            my $song = lc $Song;
+                            $stats->{word_upcase}{$song} = $Song;
+                            $stats->{chartcounts}{$song}++;
+                            $stats->{chartnicks}{$song} = $nick;
+                        }
+                    }
+
                     if (my $s = $self->{users}->{sex}{$nick}) {
                     if (my $s = $self->{users}->{sex}{$nick}) {
                         $stats->{sex_lines}{$s}++;
                         $stats->{sex_lines}{$s}++;
                         $stats->{sex_line_times}{$s}[int($hour/6)]++;
                         $stats->{sex_line_times}{$s}[int($hour/6)]++;
                     }
                     }
 
 
                     _parse_words($stats, $saying, $nick, $self->{ignorewords_regexp}, $hour);
                     _parse_words($stats, $saying, $nick, $self->{ignorewords_regexp}, $hour);
-                }
-            }
+                } # ignored
+            } # repeated
             $lastnormal = $line;
             $lastnormal = $line;
             $repeated = 0;
             $repeated = 0;
         } # normal lines
         } # normal lines
@@ -457,6 +471,15 @@ sub _parse_file
                     }
                     }
                 }
                 }
 
 
+                if ($self->{cfg}->{showcharts}) {
+                    if ($saying =~ /$self->{chartsregexp}/i) {
+                        my $song = lc $1;
+                        $stats->{word_upcase}{$song} = $1;
+                        $stats->{chartcounts}{$song}++;
+                        $stats->{chartnicks}{$song} = $nick;
+                    }
+                }
+
                 $stats->{lengths}{$nick} += length($saying);
                 $stats->{lengths}{$nick} += length($saying);
 
 
                 if (my $s = $self->{users}->{sex}{$nick}) {
                 if (my $s = $self->{users}->{sex}{$nick}) {
@@ -465,7 +488,7 @@ sub _parse_file
                 }
                 }
 
 
                 _parse_words($stats, $saying, $nick, $self->{ignorewords_regexp}, $hour);
                 _parse_words($stats, $saying, $nick, $self->{ignorewords_regexp}, $hour);
-            }
+            } # ignored
         } # action lines
         } # action lines
 
 
         # Match *** lines.
         # Match *** lines.
@@ -684,7 +707,7 @@ sub _strip_mirccodes
 
 
 sub checkname {
 sub checkname {
     # This function tracks nickchanges and puts them all in a hash->array,
     # This function tracks nickchanges and puts them all in a hash->array,
-    # so we can show all nicks that I user had later (only works properly
+    # so we can show all nicks that a user had later (only works properly
     # when nicktracking is enabled)
     # when nicktracking is enabled)
     my ($nick, $newnick, $stats) = @_;
     my ($nick, $newnick, $stats) = @_;
 
 
@@ -742,7 +765,8 @@ Morten Brix Pedersen <morten@wtf.dk>
 
 
 =head1 COPYRIGHT
 =head1 COPYRIGHT
 
 
-Copyright (C) 2001 Morten Brix Pedersen. All rights resereved.
+Copyright (C) 2001-2005 Morten Brix Pedersen. All rights resereved.
+Copyright (C) 2003-2005 Christoph Berg <cb@df7cb.de>.
 This program is free software; you can redistribute it and/or modify it
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GPL, license is included with the distribution of
 under the terms of the GPL, license is included with the distribution of
 this file.
 this file.

+ 2 - 1
pisg

@@ -5,7 +5,8 @@ use Getopt::Long;
 
 
 # pisg - Perl IRC Statistics Generator
 # pisg - Perl IRC Statistics Generator
 #
 #
-# Copyright (C) 2001-2002  <Morten Brix Pedersen> - morten@wtf.dk
+# Copyright (C) 2001-2005  <Morten Brix Pedersen> - morten@wtf.dk
+# Copyright (C) 2003-2005  Christoph Berg <cb@df7cb.de>
 #
 #
 # This program is free software; you can redistribute it and/or modify
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # it under the terms of the GNU General Public License as published by