#!/usr/bin/perl -w use strict qw(vars); use IO::Handle; use POSIX; my $usage = < ...] where is have [ ] [+] want [ ] [] price [] Each of which may appear only once, except \`have' which may appear more than once which case we calculate the differences and the profit for each one. If / is not specified at all, relevant information about shot is not reported. For have and want, specifying an empty string means zero. Entirely Missing // is taken as if both were specified and zero. In price, missing entries mean the commodity is unavailable. END ; our (@kinds) = qw(Swill Grog Fine Shot); our (@proofs) = qw(40 60 100); sub parse_info ($$$\@$) { my ($omitswgok,$default,$multishot, $storeary, $what) = @_; @ARGV or badusage("missing value for information argument \`$_'"); badusage("$what: specified more than once") if defined $storeary->[2]; my (@v) = (); while (@ARGV and $ARGV[0] =~ m/^\d/) { $_ = shift @ARGV; push @v, $_; } if (@v==1 or @v==2) { badusage("$what: swill and grog amounts must be specified") unless $omitswgok; @v=($default,$default,@v); } if ($multishot and @v==4 and length $v[3]) { $v[3] =~ m/^0*(\d+)\+0*(\d+)$/ or badusage("$what: shot must be specified as +"); $v[3] = $1 + $2; } if (@v==3) { push @v, $default; } if (@v != 4) { badusage("$what: invalid syntax (wrong number of /s)"); } my $i=0; foreach $_ (@v) { $_ = $default if !length; m/^0*(\d+)$/ or badusage("$what: $kinds[$i] \`$_': bad syntax"); $_= $1; $i++; } @$storeary = @v; } our (@have,@want,@price); sub parse_args () { @ARGV or badusage("need some information to go on"); while (@ARGV) { $_ = shift @ARGV; if (m/^have$/) { parse_info(1,0,1, @{ $have[@have] }, 'have'); } elsif (m/^want$/) { parse_info(1,0,0, @want, 'want'); } elsif (m/^price$/) { parse_info(0,1e6,0, @price, 'price'); } else { badusage("unknown information argument \`$_'"); } } } sub badusage ($) { my ($m) = @_; print STDERR "\nbad usage: $m\n\n$usage\n"; exit 16; } our $ff = '%6.1f'; sub valid ($) { my ($x) = @_; defined $x and $x>0 and $x<1e4; } sub prvff ($$\@$) { my ($what, $format, $ary, $unit) = @_; printf("%-25s", "$what:"); for my $i (qw(0 1 2 3)) { my $x= $ary->[$i]; my $y= valid($x) ? sprintf $format, $x : ' '; printf " %-9s", $y; } printf " %s\n", $unit; } sub pr ($\@$) { my ($what, $ary, $unit) = @_; prvff($what, '%4d ', @$ary, $unit); } sub prf ($\@$) { my ($what, $ary, $unit) = @_; prvff($what, $ff, @$ary, $unit); } sub pr1 ($$) { my ($k,$v) = @_; printf "%-20s %s\n", "$k:", $v; } sub fmt_stock_index ($) { my ($si) = @_; @have==1 ? '' : ' #'.$si; } our @norm_price; our ($best, $best_norm_price); sub print_inputs () { printf("%25s",''); map { printf " %5s ", $_ } @kinds; print "\n\n"; pr('prices', @price, 'poe ea.') if valid(@price); pr('target stocks', @want, 'units') if valid(@want); my $si=0; for my $stocks (@have) { pr('actual stocks'.fmt_stock_index(++$si), @$stocks, 'units'); } print "\n"; } sub compute_cheapest_rum() { return unless @price; my (@perorder) = map { $_*10 } @price; prf('equiv. ordering price', @perorder, 'poe/order'); $best= undef; $best_norm_price= 1e5; for my $i (qw(0 1 2)) { next unless $price[$i]; $norm_price[$i] = $price[$i] * 100 / $proofs[$i]; if ($norm_price[$i] <= $best_norm_price) { $best= $i; $best_norm_price= $norm_price[$i]; } }; prf('normalised prices', @norm_price, 'poe/fine'); if (defined $best) { printf "best is %-10s%*s^^\n", $kinds[$best], $best*10+10, ''; my (@bestperorder) = map { $best_norm_price * $proofs[$_] / 100 * 10; } qw(0 1 2); #push @bestperorder, $perorder[3]; prf('best is equiv. ordering', @bestperorder, 'poe/order'); } print "\n"; } sub pr1s ($) { my ($x) = @_; if (defined $x and $x) { printf ' %9.1f', $x; } else { printf " "; } } sub compute_stock_values() { return unless @have; print <[$i] * $proofs[$i] / 100; } my $rum_value= defined($best) ? $stock_rum * $best_norm_price : 0; my $shot_value= valid($price[3]) ? $stocks->[3] * $price[3] : 0; my $total_value= $rum_value + $shot_value; printf "%-10s ", 'stocks'.fmt_stock_index(++$si).':'; pr1s($stock_rum); pr1s($rum_value); printf "%6d", $stocks->[3]; pr1s($shot_value); pr1s($total_value); if (defined $last_value) { printf(" %10.1f %10.1f", $total_value - $last_value, $total_value - $initial_value); } $initial_value= $total_value unless defined $initial_value; $last_value= $total_value; print "\n"; } print <