#!/usr/local/bin/perl
use CGI qw(:standard);

#print header();
#print start_html("MAngband Character Graph");
#print h1("MAngband Character Graph");

# Main ########################################
# データ構造が苦しくなってきた．リファレンスを使わねば…
my($manglog);		# MAngband のログファイル名
my(%playTime);		# プレイ回数
my(%loginTime);		# ログイン時間
my(%killedTime);	# 殺された回数
my(%killedReason);	# 冒険者を殺したモンスター
my($restricted) = 0;	# 表示を制限するか

# デフォルト
my($subject) = "character";
my($method) = "alphabet";

#getopt モジュールを使えばいいんだが...    
if ($ARGC = @ARGV) {		# 引数がある場合
    $manglog = $ARGV[1];
    if ($ARGV[0] eq "-h") {
        print "manglog -[ahkt] logfile\n\n";
        print "-h: print this help\n";
        print "-a: character information by alphabet order(default)\n";
        print "-A: character information by alphabet order(restricted)\n";
        print "-k: character information by killed order\n";
        print "-K: character information by killed order(restricted)\n";
        print "-m: monster information\n";
        print "-t: character information by time order\n";
        print "-T: character information by time order(restricted)\n";
        exit (0);
    } elsif ($ARGV[0] eq "-a") {
        $method = "alphabet";
    } elsif ($ARGV[0] eq "-A") {
        $method = "alphabet";
        $restricted = "display";
    } elsif ($ARGV[0] eq "-k") {
        $method = "killed";
    } elsif ($ARGV[0] eq "-K") {
        $method = "killed";
        $restricted = "display";
    } elsif ($ARGV[0] eq "-m") {
        $subject = "monster";
        $method = "alphabet";
    } elsif ($ARGV[0] eq "-t") {
        $method = "time";
    } elsif ($ARGV[0] eq "-T") {
        $method = "time";
        $restricted = "display";
      } elsif ($ARGV[0] eq "-z") {
        $method = "zaru";
    } else {
#    } elsif (!($ARGV[0] =~ /^-/)) {
        $manglog = $ARGV[0];
    }
} else {       			# CGI の場合
    # param が宣言されていない場合は通りすぎるようには出来ないのだろうか？
    $restricted = param("restricted");
    $manglog = "mangband.log-" . $restricted;
    $method = param("method");
}

open (MANGLOG, $manglog) ||
    die ("can't open $manglog: $!");

while (<MANGLOG>) {
    if (/^\d+/) {
        @line = split(/\s+/);
        ($day, $month, $time, $action, $name, @rest) = @line;
        
        # 名前処理．でも名前に = が入ってると NG
        while (!($name =~ /=/)) {
            ($tmp, @rest) = @rest;
            $name .= " " . $tmp;
        }
        $name =~ /(.*)=(.*)/;
        $name = $1;
        $hostname = $2;
        
        # 残りの部分(死因，ip アドレスなど)
        $rest = join(" ", @rest);

        # 各種連想配列の初期化
#        $playTime{$name} = 0;
#        $killedTime{$name} = 0;
#        $playHour{$name} = 0;
#        $playMin{$name} = 0;
#        $playSec{$name} = 0;
        
        if ($action eq "Welcome") {
            $logintime{$name} = $time;
        } else {                    # "Goodbye"
            # パスワード間違いなどによるログインはカウントしない
            if ($rest =~ /timeout 01/) {
                next;
            }
            
            ($inHour, $inMin, $inSec) = split(/:/, $logintime{$name});
            ($outHour, $outMin, $outSec) = split(/:/, $time); 
            ($hour, $min, $sec)
                = ($outHour - $inHour, $outMin - $inMin, $outSec - $inSec);
            if ($sec < 0) {
                $sec += 60;
                $min -= 1;
            }
            if ($min < 0) {
                $min += 60;
                $hour -= 1;
            }
            if ($hour < 0) {
                $hour += 24;
            }
            $playHour{$name} += $hour;
            $playMin{$name} += $min;
            $playSec{$name} += $sec;
            
            $playTime{$name}++;
            
            if ($rest =~ /\(\"Killed by (a |an |)(.*)\"\)/) {
                $killedReason{$2}++;
                $killedTime{$name}++;
            }
        }
    } elsif (/(.*) killed by (a |an |)(.*)\./) {
        # 隠しモード．ざるざるランキング
        $zaru = $1;
        $aite = $3;
#    $zaruAite{$zaru} = $aite . " ";
        $zaruKilled{$zaru} ++;
    }
}

# 時間補正
foreach $name (sort (keys(%playTime))) {
    if ($playSec{$name} > 60) {
        $playMin{$name} += $playSec{$name} / 60;
        $playSec{$name} %= 60;
    }
    if ($playMin{$name} > 60) {
        $playHour{$name} += $playMin{$name} / 60;
        $playMin{$name} %= 60;
    }
    $sumPlayTime += $playTime{$name};
    $sumKilledTime += $killedTime{$name};
}


if ($method eq "alphabet") {
    @sortedList = sort(keys(%playTime));
} elsif ($method eq "killed") {
    @sortedList = sort by_killed (keys(%playTime));
} elsif ($method eq "logintime") {
    @sortedList = sort by_login (keys(%playTime));
} elsif ($method eq "time") {
    @sortedList = sort by_time (keys(%playTime));
}


# Header ###################################################
if ($restricted eq "recent") {
print "Content-type: text/html\n\n";
}
print <<End_of_Header;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML><HEAD>
<TITLE>MAngband Character Record</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=EUC-JP">
<LINK REV=MADE HREF="mailto:t-tanaka\@kuis.kyoto-u.ac.jp">
<LINK rel="NEXT"  href="index.html">
</HEAD>
<BODY text="#FFFFFF" link="#00FFFF" vlink="#00BBBB" alink="#CC4444" bgcolor="#000000">
<H1 align=center><font color="#98fb98">- MAngband Character Record -</font></H1>
<HR>
End_of_Header


# Body #####################################################
$rank = 0;
@ROW = ("darkgreen", "darkslategray");
$rowFlag = 0;
$prevname = $name;	# 適当に決める．ほんとは良くない

if ($subject eq "monster") {
## 死因表示
    print "<h2 align=center color=\"#98fb98\">死因</h2>\n";
    print "<h3 align=center>冥福を遂げた冒険者数 : $sumKilledTime 人</h3>\n";
    print "<table align=center border=0 cellpadding=5 cellspacing=0>\n";
    print "<tr><th align=left>モンスター<th>被害者数</tr>\n";
    foreach $reason (sort (keys (%killedReason))) {
        printf ("<tr bgcolor=\"$ROW[$rowFlag]\"><td align=left>%-40s<td align=right>%3d 人\n", $reason, $killedReason{$reason});
        $rowFlag = 1 - $rowFlag;
    }
    print "</table>\n";

  } elsif ($method eq "zaru") {
    print "ようこそ秘密の部屋へ\n";
    print "<table align=center border=0 cellpadding=5 cellspacing=0>\n<tr><th align=left>名前<th>秘密の数字<th>\n";
    foreach $name (%zaruKilled) {
                   printf "<tr><td>%s<td>%3d</tr>\n", $name, $zaruKilled{$name};
                 }
    print "</table>\n";
} elsif ($subject eq "character"){
#} else {
## キャラクタ情報表示
    if ($restricted eq "recent") {
        print "<h2 align=center><font color=\"#98fb98\">最近の状況</font></h2>\n";
    } else {
        print "<h2 align=center><font color=\"98fb98\">これまでの軌跡</font></h2>\n";
    }
    print "<h3 align=center>現在までの訪問者数 : $sumPlayTime 人</h3>\n";
    if ($restricted eq "display") {
        print "プレイ時間が1時間以下のキャラクタは除いてます\n";
    }
    print "<table align=center border=0 cellpadding=5 cellspacing=0>\n<tr><th align=center>順位<th align=left>名前<th>プレイ時間<th>ログイン回数<th>消滅回数</tr>\n";
    foreach $name (@sortedList) {
        unless (($playHour{$name} < 1) && ($restricted eq "display")) {
            $rankDummy ++;
            unless (($killedTime{$name} == $killedTime{$prevname})
                    && ($method eq "killed")) {
                $rank = $rankDummy;
            }
            printf "<tr bgcolor=\"$ROW[$rowFlag]\"><td align=center>%3d<td align=left>%-20s<td align=right>%3d時間 %02d 分 %02d 秒<td align=right>%3d 回<td align=right>%2d 回</tr>\n",
                    $rank, $name, $playHour{$name}, $playMin{$name}, 
                    $playSec{$name}, $playTime{$name}, $killedTime{$name};
            $rowFlag = 1 - $rowFlag;
        }
        $prevname = $name;
    }
    print "</table>\n";
}

close (MANGLOG);

# Footer ########################################################
print <<End_of_Footer;
<hr>
<a href="/%7Eroguelike/"><img
 src="/%7Eroguelike/pic/defbanner.gif" align=right alt="[roguelike\@lab3]" border=0 width=88 height=31></a>
<address>
Copyright &\#169;
t-tanaka<font color="#98fb98">\@</font>kuis.kyoto\-u.ac.jp
</address>
</body>
</html>
End_of_Footer
  

# Subroutine ###################################################
sub by_time {
    return (($playHour{$b} <=> $playHour{$a}) 
            || ($playMin{$b} <=> $playMin{$a})
            || ($playSec{$b} <=> $playSec{$a}));
}

sub by_login {
    return ($playTime{$b} <=> $playTime{$a});
}

sub by_killed {
    return (($killedTime{$b} <=> $killedTime{$a}) || ($a cmp $b));
}
