# $HeadURL: http://svn.mzet.net/psist/Psist.pm $
# $Author: zet $
# $Date: 2006-08-24 15:39:25 +0200 (Thu, 24 Aug 2006) $
# $Revision: 12 $

package Psist;

use strict;
use Time::Local;

sub new
{
  my $type = shift;
  my %args = @_;
  my $self = {
    profile => $args{profile},
    outfile => $args{outfile},
    silent  => $args{silent},
    verbose => 1,
    version => $args{version},
    history => 30,

    start   => time,
    now     => 0,

    jids    => {},
    nicks   => {},
    snicks  => [],
    lines   => 0,
    days    => [],
    hours   => []
  };
  my ($mday,$mon,$year) = (localtime(time))[3,4,5];
  $self->{now} = timelocal(0, 0, 0, $mday, $mon, $year);
  
  my $i = 0;
  my $j = 0;
  while($i < $self->{history}) {
    while($j < 4) {
      $self->{days}[$i][$j] = 0;
      $j++;
    }
    $j = 0;
    $i++;
  }

  $i = 0;
  while($i < 24) {
    $self->{hours}[$i] = 0;
    $i++;
  }

  bless($self, $type);
  return $self;
}

sub run
{
  my $self = shift;
  my $time;
  
  print "psist v$self->{version} - PSI Statistics Generator\n\n" unless $self->{silent};

  $self->load_config();
  $self->parse_history();
  $self->gen_html();

  $time = time - $self->{start};
  print "\n",'DONE. Generated in ',sprintf('%02d:%02d:%02d', $time / 3600, ($time % 3600) / 60, ($time % 3600) % 60),"\n";
}

sub load_config
{
  my $self = shift;
  my $row;
  my $i;
  my $nick;
  my $jid;
  
  print "loading contacts...\n" unless $self->{silent};
  open(CONFIGXML, $self->{profile} . "/accounts.xml");
  while($row = <CONFIGXML>) {
    if($row =~ /<name type="QString"[^>]*>(.*?)<\/name>/) {
        $nick = $1;
    }
    if($row =~ /<jid type="QString"[^>]*>(.*?)<\/jid>/) {
      if(length($1) == 0) {
          next;
      }
      if (length($nick) == 0) {
          $nick = $jid;
      }
      $jid = $1;
      $self->{jids}{$jid} = $nick;
      $self->{nicks}{$nick}{lines} = 0;
      $self->{nicks}{$nick}{linest}[0] = 0;
      $self->{nicks}{$nick}{linest}[1] = 0;
      $self->{nicks}{$nick}{linest}[2] = 0;
      $self->{nicks}{$nick}{linest}[3] = 0;
      $self->{nicks}{$nick}{to} = 0;
      $self->{nicks}{$nick}{sfrom} = 0;
      $self->{nicks}{$nick}{sto} = 0;
      $self->{nicks}{$nick}{last} = 0;
    }
  }
  close(CONFIGXML);
}

sub parse_history
{
  my $self = shift;
  my ($jidf,$nick);
  my ($row,$ts,$tsfull,$dago,$dp);

  print "parsing history data...\n" unless $self->{silent};
  foreach my $jid (keys %{$self->{jids}}) {
    $nick = $self->{jids}{$jid};
    $jidf = $jid;
    $jidf =~ s/@/_at_/;
    $jidf =~ s/\+/%2b/;
    open(HISTFIL, $self->{profile} . '/history/' . $jidf . '.history') or next;
    print '  >> "',$jid,'" (',$nick,')',"\n" if $self->{verbose};
    while($row = <HISTFIL>) {

      # row processing
      if($row =~ /^\|(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\|1\|([a-z]+)\|.{4}\|(.*)/) {
        $ts = timelocal(0, 0, 0, $3, $2 - 1, $1);
        $tsfull = timelocal($6, $5, $4, $3, $2 - 1, $1);
        $dp = ($4 < 6) ? 0 : (($4 < 12) ? 1 : (($4 < 18) ? 2 : 3));
        $dago = int(($self->{now} - $ts) / 86400);
        if($dago < $self->{history}) {
          $self->{days}[$dago][$dp]++;
        }
        $self->{hours}[$4]++;
        $self->{lines}++;

        $self->{nicks}{$nick}{lines}++;
        $self->{nicks}{$nick}{linest}[$dp]++;
        if($7 eq 'to') {
          $self->{nicks}{$nick}{to}++;
        }
        if($self->{nicks}{$nick}{last} < $tsfull) {
          $self->{nicks}{$nick}{last} = $tsfull;
        }
      }
    }
    close(HISTFIL);
  }
  
  print "sorting contacts by lines count...\n" unless $self->{silent};
  @{$self->{snicks}} = sort { $self->{nicks}{$b}{lines} <=> $self->{nicks}{$a}{lines} } keys %{$self->{nicks}};
}

sub gen_html
{
  my $self = shift;

  my ($sec,$min,$hour,$mday,$mon,$year) = (localtime(time));
  my ($max_d,$max_h,$sum_h,$i,$sum);
  my ($time,$nick);
  
  $mon++;
  $year += 1900;

  # max for days
  $max_d = 1;
  $i = $self->{history};
  while($i > 0) {
    $i--;
    $sum = $self->{days}[$i][0] + $self->{days}[$i][1] + $self->{days}[$i][2] + $self->{days}[$i][3];
    $max_d = ($sum > $max_d) ? $sum : $max_d;
  }

  # max and sum for hours
  $max_h = 0;
  $sum_h = 0;
  $i = 0;
  while($i < 24) {
    $sum_h += $self->{hours}[$i];
    $max_h = ($self->{hours}[$i] > $max_h) ? $self->{hours}[$i] : $max_h;
    $i++;
  }
  $max_h = ($max_h == 0) ? 1 : $max_h;
  $sum_h = ($sum_h == 0) ? 1 : $sum_h;
  

  print "generating HTML file...\n" unless $self->{silent};
  open(HTMLFIL, '> '.$self->{outfile});
  print HTMLFIL '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',"\n";
  print HTMLFIL '<html>',"\n";
  print HTMLFIL '<head>',"\n";
  print HTMLFIL '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />',"\n";
  print HTMLFIL '<title>',$self->translate('PSI Statistics'),'</title>',"\n";
  print HTMLFIL '<link type="text/css" rel="stylesheet" href="style.css" media="screen,projection" />',"\n";
  print HTMLFIL '</head>',"\n";
  print HTMLFIL '<body>',"\n";
  print HTMLFIL '<div align="center">',"\n";
  print HTMLFIL '<span class="title">',$self->translate('PSI Statistics'),'</span><br /><br />',"\n";
  print HTMLFIL $self->translate('Statistics have been generated at '),'"',sprintf('%02d.%02d.%d %02d:%02d:%02d', $mday, $mon, $year, $hour, $min, $sec),'"<br /><br /><br />',"\n";

  # daily activity
  print HTMLFIL '<div class="headtext">',$self->translate('Daily activity'),'</div>',"\n";
  print HTMLFIL '<table border="0"><tr>',"\n";
  $i = $self->{history};
  while($i > 0) {
    $i--;
    $sum = $self->{days}[$i][0] + $self->{days}[$i][1] + $self->{days}[$i][2] + $self->{days}[$i][3];
    print HTMLFIL '<td align="center" valign="bottom" class="asmall">',$sum,'<br />',"\n";
    print HTMLFIL '<img src="./red-v.png" width="15" height="',int($self->{days}[$i][3] * 100 / $max_d),'" alt="',$sum,'" title="',$sum,'" /><br />',"\n";
    print HTMLFIL '<img src="./yellow-v.png" width="15" height="',int($self->{days}[$i][2] * 100 / $max_d),'" alt="',$sum,'" title="',$sum,'" /><br />',"\n";
    print HTMLFIL '<img src="./green-v.png" width="15" height="',int($self->{days}[$i][1] * 100 / $max_d),'" alt="',$sum,'" title="',$sum,'" /><br />',"\n";
    print HTMLFIL '<img src="./blue-v.png" width="15" height="',int($self->{days}[$i][0] * 100 / $max_d),'" alt="',$sum,'" title="',$sum,'" /><br />',"\n";
    print HTMLFIL '</td>',"\n";
  }
  print HTMLFIL '</tr><tr>',"\n";
  $i = $self->{history};
  while($i > 0) {
    $i--;
    print HTMLFIL '<td class="rankc10center" align="center">',$i,'</td>',"\n";
  }
  print HTMLFIL '</tr></table>',"\n";
  print HTMLFIL '<table align="center" border="0" width="520"><tr>',"\n";
  print HTMLFIL '<td align="center" class="asmall"><img src="./blue-h.png" width="40" height="15" align="middle" alt="0-5" /> = 0-5</td>',"\n";
  print HTMLFIL '<td align="center" class="asmall"><img src="./green-h.png" width="40" height="15" align="middle" alt="6-11" /> = 6-11</td>',"\n";
  print HTMLFIL '<td align="center" class="asmall"><img src="./yellow-h.png" width="40" height="15" align="middle" alt="12-17" /> = 12-17</td>',"\n";
  print HTMLFIL '<td align="center" class="asmall"><img src="./red-h.png" width="40" height="15" align="middle" alt="18-23" /> = 18-23</td>',"\n";
  print HTMLFIL '</tr></table><br />',"\n";
  
  # most active times
  print HTMLFIL '<div class="headtext">',$self->translate('Most active times'),'</div>',"\n";
  print HTMLFIL '<table border="0"><tr>',"\n";
  $i = 0;
  while($i < 24) {
    print HTMLFIL '<td align="center" valign="bottom" class="asmall">',sprintf('%.1f', $self->{hours}[$i] * 100 / $sum_h),'%<br /><img src="./',(($i < 6) ? 'blue' : (($i < 12) ? 'green' : (($i < 18) ? 'yellow' : 'red' ))),'-v.png" width="15" height="',int($self->{hours}[$i] * 100 / $max_h),'" alt="',$self->{hours}[$i],'" title="',$self->{hours}[$i],'"/></td>',"\n";
    $i++;
  }
  print HTMLFIL '</tr><tr>',"\n";
  $i = 0;
  while($i < 24) {
    print HTMLFIL '<td class="',(($self->{hours}[$i] == $max_h) ? 'hi' : ''),'rankc10center" align="center">',$i,'</td>',"\n";
    $i++;
  }
  print HTMLFIL '</tr></table><br />',"\n";

  # contacts
  print HTMLFIL '<div class="headtext">',$self->translate('Contacts'),'</div>',"\n";
  print HTMLFIL '<table border="0" width="794">',"\n";
  print HTMLFIL '<tr><td>&nbsp;</td><td class="tdtop" width="25%">',$self->translate('Nick'),'</td><td class="tdtop" style="text-align: right" width="12%">',$self->translate('Posts'),'</td><td class="tdtop" width="65">',$self->translate('Time'),'</td><td class="tdtop" width="10%">',$self->translate('To'),'</td><td class="tdtop" width="10%">',$self->translate('From'),'</td><td class="tdtop" width="25%">',$self->translate('Last message'),'</td></tr>',"\n";
  $i = 0;
  foreach $nick (@{$self->{snicks}}) {
    $i++;
    if($self->{nicks}{$nick}{lines} > 0) {
      $sum = $self->{nicks}{$nick}{linest}[0] + $self->{nicks}{$nick}{linest}[1] + $self->{nicks}{$nick}{linest}[2] + $self->{nicks}{$nick}{linest}[3];
      $sum = ($sum > 0) ? $sum : 1;
      my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($self->{nicks}{$nick}{last}));
      $year += 1900;
      $mon++;
      print HTMLFIL '<tr><td class="',(($i == 1) ? 'hi' : ''),'rankc">',$i,'</td><td style="background-color: #babadc">', $nick, '</td><td style="background-color: #babadc; text-align: right">',$self->{nicks}{$nick}{lines},'</td><td style="background-color: #babadc; text-align: center">';
      print HTMLFIL '<img src="./blue-h.png" border="0" width="',int($self->{nicks}{$nick}{linest}[0] * 60 / $sum),'" height="15" alt="',$self->{nicks}{$nick}{linest}[0],'" title="',$self->{nicks}{$nick}{linest}[0],'" />';
      print HTMLFIL '<img src="./green-h.png" border="0" width="',int($self->{nicks}{$nick}{linest}[1] * 60 / $sum),'" height="15" alt="',$self->{nicks}{$nick}{linest}[1],'" title="',$self->{nicks}{$nick}{linest}[1],'" />';
      print HTMLFIL '<img src="./yellow-h.png" border="0" width="',int($self->{nicks}{$nick}{linest}[2] * 60 / $sum),'" height="15" alt="',$self->{nicks}{$nick}{linest}[2],'" title="',$self->{nicks}{$nick}{linest}[2],'" />';
      print HTMLFIL '<img src="./red-h.png" border="0" width="',int($self->{nicks}{$nick}{linest}[3] * 60 / $sum),'" height="15" alt="',$self->{nicks}{$nick}{linest}[3],'" title="',$self->{nicks}{$nick}{linest}[3],'" />';
      print HTMLFIL '</td><td style="background-color: #babadc">',sprintf('%.2f', $self->{nicks}{$nick}{to} * 100 / $self->{nicks}{$nick}{lines}),'%</td><td style="background-color: #babadc">',sprintf('%.2f', 100 - $self->{nicks}{$nick}{to} * 100 / $self->{nicks}{$nick}{lines}),'%</td>';
      print HTMLFIL '<td style="background-color: #babadc">',sprintf('%02d.%02d.%d %02d:%02d:%02d', $mday, $mon, $year, $hour, $min, $sec),'</td>';
      print HTMLFIL '</tr>',"\n";
    }
  }
  print HTMLFIL '</table><br />',"\n";
  
  # footer
  print HTMLFIL $self->translate('Total number of lines'),': ',$self->{lines},'<br /><br />',"\n";
  print HTMLFIL '<span class="small">',"\n";
  print HTMLFIL $self->translate('Stats generated by'),' <a href="http://www.mzet.net/psist" class="background">psist</a> v',$self->{version},'<br />',"\n";
  print HTMLFIL 'psist by <a href="http://www.mzet.net/" class="background">Michal Zbortek (zet)</a><br />',"\n";
  $time = time - $self->{start};
  print HTMLFIL $self->translate('Stats generated in'),' ',sprintf('%02d:%02d:%02d', $time / 3600, ($time % 3600) / 60, ($time % 3600) % 60),"\n";
  print HTMLFIL '</span>',"\n";
  
  print HTMLFIL '</div>',"\n";
  print HTMLFIL '</body>',"\n";
  print HTMLFIL '</html>',"\n";
  close(HTMLFIL);
}

sub translate
{
  my $self = shift;
  my $message = shift;
  
  return $message;
}

return 1;

