#!/usr/bin/perl -w
use Math::Calc::Units qw(convert readable calc);

sub usage {
    my ($msg, $bad) = @_;
    my $out = $bad ? *STDERR : *STDOUT;

    if ($msg) {
	print $out "$0: $msg\n";
    }
   
    print $out <<"END";
usage:

Calculate the given expression, and guess human-readable units for the result:
    $0 [-v] <expr>

Convert the given expression to the requested units:
    $0 -c <expr> <unit>
    $0 --convert <expr> <unit>

Examples:
How long does it take to download 10MB over a 384 kilobit/sec connection?
    $0 "10MB / 384Kbps"

What is the expected I/O rate for 8KB reads on a disk that reads at 20MB/sec
and has an average seek time of 15ms?
    $0 "8KB / (8KB/(20MB/sec) + 15ms)"

Or if you prefer to calculate that by figuring out the number of seconds
per byte and inverting:
    $0 "((1sec/20MB) + 15ms/8KB) ** -1"

How many gigabytes can you transfer in a week at 2MB/sec?
    $0 -c "2MB/sec" "GB/week"

How many angels fit on the heads of 17 pins (with some assumptions)?
(This demonstrates that unknown units are allowed.)
    $0 "42 angels/pinhead * 17 pinheads"
END

    exit($bad ? 1 : 0);
}

my $verbose = 0;
my $action = 'readable';

my @args;
while (@ARGV) {
    $_ = shift(@ARGV);
    if ($_ eq '-v')          { $verbose = 1; }
    elsif (/^-c|--convert$/) { $action = 'convert'; }
    elsif (/^-h|--help$/)    { usage("", 0); }
    else                     { push @args, $_; }
}

if ($action eq 'convert') {
    usage("not enough args", 1) if (@args < 2);
    usage("too many args", 1) if (@args > 2);
    print convert($args[0], $args[1]), "\n";
} elsif ($action eq 'readable') {
    usage("", 0) if @args == 0;
    usage("too many args", 1) if (@args > 1);
    print "$_\n" foreach readable($args[0], $verbose);
}

1;
