Mercurial > hg > batmud > misc
view magestats.pl @ 73:54e33015ba7c misc
Lots of fixes, and minor improvements.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 09 Apr 2010 16:16:01 +0000 |
parents | bc05f9d391bb |
children | 6483aa47f297 |
line wrap: on
line source
#!/usr/bin/perl -w # Magestats - BatMUD Mage guild statistics generator # Developed by Matti Hämäläinen (Ggr), <ccr@tnsp.org> # (C) Copyright 2010 Tecnic Software productions (TNSP) # # Requires Perl 5.8 and following modules: # In Debian / Ubuntu, apt-get install libgd-graph-perl use strict; use Data::Dumper; use GD::Graph; use GD::Graph::linespoints; # List of spells per damage type. Only major blasts/areas. my %spell_data = ( "acid" => [ "acid blast", "acid storm", "acid ray", "acid rain", "acid arrow", "acid wind", "disruption" ], "fire" => [ "lava blast", "lava storm", "meteor blast", "meteor swarm", "fire blast", "fire bolt", "flame arrow" ], "elec" => [ "electrocution", "lightning storm", "forked lightning", "chain lightning", "blast lightning", "lightning bolt", "shocking grasp" ], "pois" => [ "summon carnal spores","killing cloud", "power blast", "venom strike", "poison blast", "poison spray", "thorn spray" ], "cold" => [ "cold ray", "hailstorm", "ice bolt", "cone of cold", "darkfire", "flaming ice", "chill touch" ], "mana" => [ "golden arrow", "magic eruption", "summon greater spores", "magic wave", "levin bolt", "summon lesser spores", "magic missile" ], "asph" => [ "blast vacuum", "vacuum globe", "strangulation", "chaos bolt", "vacuum ball", "suffocation", "vacuumbolt" ], ); # Settings and defaults my $progName = "magestats.pl"; my $opt_cachefile; my $opt_verbosity = 1; my $opt_prefix = "magestats"; my $opt_imgfmt = "png"; my $opt_noinput = 0; my $opt_width = 500; my $opt_height = 250; # Log level support sub mlog($$) { my $level = shift; my $msg = shift; print STDERR "* $msg\n" if ($opt_verbosity >= $level); } ### ### Print out help if no arguments given ### my $opt_mode = shift or die( "Magestats v0.4 - BatMUD Mage guild statistics generator Developed by Matti Hamalainen (Ggr \@ bat), <ccr\@tnsp.org> (C) Copyright 2010 Tecnic Software productions (TNSP) Usage: $progName dump [options] < logfile $progName stats [options] < logfile -v Verbose mode -c <cachefile> Specify a cache file to restore from -p <prefix> Output filename prefix ('$opt_prefix') -t <png|gif> Image format to be used ('$opt_imgfmt') -s <WxH> Graph dimensions in pixels ($opt_width x $opt_height) -n No input (only handle cache, if specified) "); die("Invalid operation mode '$opt_mode'!\n") unless ($opt_mode =~ /^(dump|stats)$/); while (my $opt = shift) { if ($opt eq "-c") { # Restore cache from file $opt_cachefile = shift or die("-c option requires an argument.\n"); } elsif ($opt eq "-v") { $opt_verbosity++; } elsif ($opt eq "-t") { $opt_imgfmt = shift or die("-t option requires an argument.\n"); die("Invalid format '$opt_imgfmt' specified!\n") unless ($opt_imgfmt =~ /^(png|gif)$/); } elsif ($opt eq "-p") { $opt_prefix = shift or die("-p option requires an argument.\n"); } elsif ($opt eq "-n") { $opt_noinput = 1; } } ### ### Construct full data structure ### mlog(1, "Initializing structures."); my $spells = {}; foreach my $type (keys %spell_data) { my $src = $spell_data{$type}; foreach my $spell (@{$src}) { $spells->{$spell}{"type"} = $type; $spells->{$spell}{"blasts"} = 0; } $spells->{$type}{"essence"}{"increase"} = 0; $spells->{$type}{"essence"}{"blasts"}{"single"} = []; $spells->{$type}{"essence"}{"blasts"}{"area"} = []; $spells->{$type}{"reagents"} = 0; $spells->{$type}{"single"} = $src->[0]; $spells->{$type}{"area"} = $src->[1]; push(@{$spells->{"single"}}, $src->[0]); push(@{$spells->{"area"}}, $src->[1]); } $spells->{"total"}{"blasts"} = 0; $spells->{"total"}{"essence"} = 0; $spells->{"total"}{"reagents"} = 0; sub get_spell_type($) { my $spell = $_[0]; die("get_spell_type($spell): No such spell.\n") unless exists($spells->{$spell}{"type"}); return $spells->{$spell}{"type"}; } ### ### Read cache ### if (defined($opt_cachefile)) { mlog(1, "Restoring cache from '$opt_cachefile'."); open(CACHE, "<", $opt_cachefile) or die("Could not open cache file '$opt_cachefile'!\n"); my $s = <CACHE>; close(CACHE); eval $s; } ### ### Scan input for blasts etc. ### my @all_spells = (); foreach my $type (keys %spell_data) { push(@all_spells, @{$spell_data{$type}}); } my $match = join("|", @all_spells); my $essence_flag = 0; my $last_spell = ""; #print STDERR "$match\n"; if ($opt_noinput) { mlog(1, "Skipping input parsing."); } else { mlog(1, "Parsing log from stdin..."); while (defined(my $s = <STDIN>)) { if ($s =~ /^You watch with selfpride as your ($match) hits / || $s =~ /^You hit .+ with your ($match)\.$/ || $s =~ /^Your ($match) hits /) { $last_spell = $1; $spells->{$last_spell}{"blasts"}++; $spells->{"total"}{"blasts"}++; # If essence was gained, get the type etc .. if ($essence_flag) { my $type = get_spell_type($last_spell); $spells->{$type}{"essence"}{"increase"}++; # Save amount of major blasts for each "essence gain" step foreach my $class ("single", "area") { my $name = $spells->{$type}{$class}; push(@{$spells->{$type}{"essence"}{"blasts"}{$class}}, $spells->{$name}{"blasts"}); } $essence_flag = 0; } } elsif ($s =~ /^Your knowledge in elemental powers helps you to save the reagent for further use\./) { $spells->{get_spell_type($last_spell)}{"reagents"}++; $spells->{"total"}{"reagents"}++; } elsif ($s =~ /^You feel your skills in handling elemental forces improve\./) { $essence_flag = 1; $spells->{"total"}{"essence"}++; } } } ### ### Dump cache to stdout ### if ($opt_mode eq "dump") { $Data::Dumper::Indent = 0; $Data::Dumper::Useqq = 1; $Data::Dumper::Purity = 1; my $dumper = Data::Dumper->new([$spells], ["spells"]); print $dumper->Dump(); exit; } ### ### Output statistics ### if ($opt_mode eq "stats") { my $filename = $opt_prefix.".html"; open(OUT, ">", $filename) or die("Could not create output file '$filename'.\n"); mlog(1, "Outputting stats HTML to '$filename'"); print OUT qq| <html> <head> <title>Mage statistics</title> </head> <body> <h1>Mage statistics</h1> <table border=\"1\"> <tr> <th>Type</th> <th>Blasts</th> <th>Reagents saved</th> <th>Essence gained</th> <th>Blasts per essence gain</th> </tr> |; my $major_blasts = 0; foreach my $type (sort { $a cmp $b } keys %spell_data) { my $s_s = $spells->{$type}{"single"}; my $s_a = $spells->{$type}{"area"}; my $b_s = $spells->{$s_s}{"blasts"}; my $b_a = $spells->{$s_a}{"blasts"}; $major_blasts += $b_s + $b_a; print OUT "<tr><td>$type</td><td> <table border=\"1\"><th></th><th>Single</th><th>Area</th></tr> <tr><th>Name</th><td>$s_s</td><td>$s_a</td></tr> <tr><th>Blasts</th><td>".$b_s."</td><td>".$b_a."</td></tr> </table>"; my $total_blasts = $b_s + $b_a; printf OUT "</td><td><b>%d</b> (%1.2f %%)</td><td>%d</td><td>", $spells->{$type}{"reagents"}, ($total_blasts > 0) ? ($spells->{$type}{"reagents"} * 100.0) / $total_blasts : 0.0, $spells->{$type}{"essence"}{"increase"}; if (exists($spells->{$type}{"essence"}{"blasts"})) { print OUT "<img src=\"".$opt_prefix."_".$type.".".$opt_imgfmt."\" alt=\"?\" />"; } print OUT " </td> </tr>\n"; } print OUT "</table> <p> Total major blasts: <b>".$major_blasts."</b><br /> Total blasts: <b>".$spells->{"total"}{"blasts"}."</b> (including minor)<br /> Total reagents saved: <b>".$spells->{"total"}{"reagents"}."</b><br /> Total essence gained: <b>".$spells->{"total"}{"essence"}."</b><br /> </p> </body> </html> "; mlog(1, "Outputting graphs '".$opt_prefix."_*.".$opt_imgfmt."'..."); foreach my $type (sort { $a cmp $b } keys %spell_data) { my $s = $spells->{$type}{"single"}; my $a = $spells->{$type}{"area"}; my $graph = GD::Graph::linespoints->new($opt_width, $opt_height); $graph->set( y_label => 'Blasts', x_label => 'Essence gained', ); my @titles = (); my @total = (); for (my $i = 1; $i <= $spells->{$type}{"essence"}{"increase"}; $i++) { push(@titles, "+".$i); } for (my $i = 0; $i < $spells->{$type}{"essence"}{"increase"}; $i++) { push(@total, $spells->{$type}{"essence"}{"blasts"}{"single"}[$i] + $spells->{$type}{"essence"}{"blasts"}{"area"}[$i]); } my @data = ( \@titles, $spells->{$type}{"essence"}{"blasts"}{"single"}, $spells->{$type}{"essence"}{"blasts"}{"area"}, \@total, ); my $gd = $graph->plot(\@data) or mlog(0, "Error creating graph ($type): ".$graph->error); if ($gd) { open(IMG, ">", $opt_prefix."_".$type.".".$opt_imgfmt) or die("Error openiong file ".$!."\n"); binmode IMG; print IMG $gd->gif if ($opt_imgfmt eq "gif"); print IMG $gd->png if ($opt_imgfmt eq "png"); close IMG; } } }