#!/usr/bin/perl
#
# dizeg - uses Games::Dice::Probability and GD::Graph to create distribution 
#         charts for a given dice expression.
#
# Takes a single argument of a dice expression such as "2d6" or "3d4"
# or "2d10+(2d12/1d4)*1d8" and calculates the value/probability distribution
# then does a quick and dirty output of it to STDOUT.  Or, given an outfile via
# the -o option, will write the image to the file.
#
# This and other hacks can be found at: http://oddgeek.info/
#
# Copyright (c) 2005 Jason A. Dour
#
# This software is provided 'as-is', without any express or implied warranty.
# In no event will the authors be held liable for any damages arising from the
# use of this software.
#
# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:
#
#     1. The origin of this software must not be misrepresented; you must not
#     claim that you wrote the original software. If you use this software in a
#     product, an acknowledgment in the product documentation would be
#     appreciated but is not required.
#
#     2. Altered source versions must be plainly marked as such, and must not
#     be misrepresented as being the original software.
#
#     3. This notice may not be removed or altered from any source
#     distribution.
#

#
# Version Information
#
# 1.0	2005.10.06
#
# 	Quick hack using me Games::Dice::Probability module and GD::Graph to
# 	quickly create distribution charts.  Very handy.  Not perfect, and could
# 	certainly use a bit of polishing, but what do you expect from a quick
# 	hack?
#



#
# Load the necessary modules.
use Games::Dice::Probability;
use GD::Graph::lines;
use Getopt::Regex qw(GetOptions);



#
# Play nice.
use strict;
use warnings;
use Carp;



#
# Global defines.
our $OutputFile;

#
# $progname
#       The name of the script.
our $progname = $0;
$progname =~ s/.*\///;



#
# usage()
#     Pretty-print the usage for the user.
sub usage {
    print STDERR <<PEND ;
$progname: error: @_
$progname: usage: $progname [-o outputfilename] dice_expression
                -o outputfilename
                        output graph data to given filename i
			rather than STDOUT
PEND

    exit(99);
} 

#
# error()
#     Pretty-print all errors and exit with error code.
sub error {
    my $exitval = shift();
    
    print STDERR "$progname: error: @_\n";
    
    exit($exitval);
} 



#
# MAIN

#
# Handle command line.
GetOptions(
    \@ARGV,
    ['^-o$', sub {
	if ( length($_[0]) ) {
	    $OutputFile = $_[0];
	} else {
	    usage("No output file specified.");
	}
    }, 1],
    ['^(-.*)$', sub { usage("Invalid option ($1)."); }, 0],
);

#
# Create GDP object based on dice expression on the command line.
my $dice;
if ( $#ARGV >= 0 ) {
    $dice = Games::Dice::Probability->new($ARGV[0]);
} else {
    error(10,"No dice expression provided.");
}

#
# Get the distribution as a hash.
my $dist = $dice->distribution();

#
# Build the X and Y axes data arrays...
my @x;
my @y;
# ...by looping over every value from lowest to highest...
foreach my $key ( sort {$a+0 <=> $b+0} keys(%$dist) ) {
    # ...and pushing the value onto the x axis...
    push(@x,$key);
    # ...and pushing the combinations on the y axis...
    push(@y,$$dist{$key});
}

#
# The dataset for the graph...
my @data = ( \@x, \@y );

#
# Create the GD::Graph object.
my $graph = GD::Graph::lines->new(700,400);

#
# Set the graph parameters.
$graph->set( 
    x_label => "Value", 
    y_label => "Combinations", 
    title => "Distribution for \'$ARGV[0]\'",
    line_width => "3",
    show_values => 1,
    values_vertical => 1,
    values_space => 6,
) || error(11,"Could not set graph parameters (" . $graph->error . ").");

#
# Plot the graph.
my $image = $graph->plot(\@data) ||
    error(12,"Could not plot graph (" . $graph->error . ").");

#
# Print the graph as a PNG format image to either STDOUT or OutputFile.
if ( length($OutputFile) ) {
    open(OUTFILE,">$OutputFile") ||
        error(13,"Could not open outfile ($OutputFile) for output!");
    print OUTFILE $image->png;
    close(OUTFILE);
} else {
    print $image->png;
}

#
# We're done.
exit(0);
