chiark / gitweb /
Improvements to financial table
[ypp-sc-tools.web-live.git] / ypp-restock-rum
index b76d1c4ccfd349fd6331b2f126dadce9d108cf1b..96e6867f7ad0564cdc518a64dec2e8c5b3894eba 100755 (executable)
@@ -17,12 +17,10 @@ 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.
 
 more than once which case we calculate the differences and the profit
 for each one.
 
-If /<shot> is not specified at all, relevant information about shot is
-not reported.  For have and want, specifying an empty string means
-zero.  Entirely Missing <swill>/<grog>/ is taken as if both were
-specified and zero.
+If <shot> is not specified at all, relevant information about shot is
+not reported.  For have and want, missing entries count as zero.
 
 
-In price, missing entries mean the commodity is unavailable.
+In price, \`x' means the commodity is unavailable.
 END
 ;
 
 END
 ;
 
@@ -35,7 +33,7 @@ sub parse_info ($$$\@$) {
     badusage("$what: specified more than once")
        if defined $storeary->[2];
     my (@v) = ();
     badusage("$what: specified more than once")
        if defined $storeary->[2];
     my (@v) = ();
-    while (@ARGV and $ARGV[0] =~ m/^\d/) {
+    while (@ARGV and $ARGV[0] =~ m/^\d|^x$/) {
        $_ = shift @ARGV;
        push @v, $_;
     }
        $_ = shift @ARGV;
        push @v, $_;
     }
@@ -53,13 +51,17 @@ sub parse_info ($$$\@$) {
        push @v, $default;
     }
     if (@v != 4) {
        push @v, $default;
     }
     if (@v != 4) {
-       badusage("$what: invalid syntax (wrong number of /s)");
+       badusage("$what: invalid syntax (wrong number of parameters)");
     }
     my $i=0;
     foreach $_ (@v) {
     }
     my $i=0;
     foreach $_ (@v) {
-       $_ = $default if !length;
-       m/^0*(\d+)$/ or badusage("$what: $kinds[$i] \`$_': bad syntax");
-       $_= $1;
+       if ($default>0 and m/^x$/) {
+           $_ = $default;
+       } elsif (m/^0*(\d+)$/) {
+           $_= $1;
+       } else {
+           badusage("$what: $kinds[$i] \`$_': bad syntax");
+       }
        $i++;
     }
     @$storeary = @v;
        $i++;
     }
     @$storeary = @v;
@@ -76,7 +78,7 @@ sub parse_args () {
        } elsif (m/^want$/) {
            parse_info(1,0,0, @want, 'want');
        } elsif (m/^price$/) {
        } elsif (m/^want$/) {
            parse_info(1,0,0, @want, 'want');
        } elsif (m/^price$/) {
-           parse_info(0,1e6,0, @price, 'price');
+           parse_info(0,1e7,0, @price, 'price');
        } else {
            badusage("unknown information argument \`$_'");
        }
        } else {
            badusage("unknown information argument \`$_'");
        }
@@ -93,7 +95,7 @@ our $ff = '%6.1f';
 
 sub valid ($) {
     my ($x) = @_;
 
 sub valid ($) {
     my ($x) = @_;
-    defined $x and $x>0 and $x<1e4;
+    defined $x and $x and $x<1e5;
 }    
 
 sub prvff ($$\@$) {
 }    
 
 sub prvff ($$\@$) {
@@ -126,6 +128,15 @@ sub fmt_stock_index ($) {
     @have==1 ? '' : ' #'.$si;
 }
 
     @have==1 ? '' : ' #'.$si;
 }
 
+sub rum_total (\@) {
+    my ($rums) = @_;
+    my $total= 0;
+    foreach my $i (qw(0 1 2)) {
+       $total += $rums->[$i] * $proofs[$i] / 100;
+    }
+    return $total;
+}
+
 our @norm_price;
 our ($best, $best_norm_price);
 
 our @norm_price;
 our ($best, $best_norm_price);
 
@@ -149,7 +160,7 @@ sub compute_cheapest_rum() {
     prf('equiv. ordering price', @perorder, 'poe/order');
 
     $best= undef;
     prf('equiv. ordering price', @perorder, 'poe/order');
 
     $best= undef;
-    $best_norm_price= 1e5;
+    $best_norm_price= 1e6;
     for my $i (qw(0 1 2)) {
        next unless $price[$i];
        $norm_price[$i] = $price[$i] * 100 / $proofs[$i];
     for my $i (qw(0 1 2)) {
        next unless $price[$i];
        $norm_price[$i] = $price[$i] * 100 / $proofs[$i];
@@ -175,7 +186,7 @@ sub compute_cheapest_rum() {
 
 sub pr1s ($) {
     my ($x) = @_;
 
 sub pr1s ($) {
     my ($x) = @_;
-    if (defined $x and $x) {
+    if (valid($x)) {
        printf ' %9.1f', $x;
     } else {
        printf "          ";
        printf ' %9.1f', $x;
     } else {
        printf "          ";
@@ -184,27 +195,30 @@ sub pr1s ($) {
 
 sub compute_stock_values() {
     return unless @have;
 
 sub compute_stock_values() {
     return unless @have;
-    print <<END
+    print @have>1 ? <<END
                  Rum      Rum     Shot    Shot     total      Profit    Profit
                 equiv.   value   stocks   value    value      this leg   total
 END
                  Rum      Rum     Shot    Shot     total      Profit    Profit
                 equiv.   value   stocks   value    value      this leg   total
 END
+: <<END
+                             Rum      Rum             Shot    Shot     total
+                            equiv.   value           stocks   value    value
+END
 ;
 
     my $initial_value;
     my $last_value;
     my $si=0; for my $stocks (@have) {
 ;
 
     my $initial_value;
     my $last_value;
     my $si=0; for my $stocks (@have) {
-       my $stock_rum= 0;
-       foreach my $i (qw(0 1 2)) {
-           $stock_rum += $stocks->[$i] * $proofs[$i] / 100;
-       }
+       my $stock_rum = rum_total(@$stocks);
        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).':';
        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).':';
+       print '            ' if @have==1;
        pr1s($stock_rum);
        pr1s($rum_value);
        pr1s($stock_rum);
        pr1s($rum_value);
-       printf "%6d", $stocks->[3];
+       print '        ' if @have==1;
+       printf "%6s", $stocks->[3] ? $stocks->[3] : '';
        pr1s($shot_value);
        pr1s($total_value);
        
        pr1s($shot_value);
        pr1s($total_value);
        
@@ -217,94 +231,91 @@ END
        $last_value= $total_value;
        print "\n";
     }
        $last_value= $total_value;
        print "\n";
     }
-    print <<END
+    print @have>1 ? <<END
                  fine      poe    units    poe       poe     delta-poe     poe
                  fine      poe    units    poe       poe     delta-poe     poe
-
+END
+: <<END
+                             fine      poe            units    poe       poe
 END
 ;
 END
 ;
+    print "\n";
 }
 
 }
 
-parse_args();
-print_inputs();
-compute_cheapest_rum();
-compute_stock_values();
+sub pr2 ($$$) {
+    my ($k,$v1,$v2) = @_;
+    printf "%-25s %-23s %s\n", "$k:", $v1, $v2;
+}
 
 
-__DATA__
+sub pr2rs ($$$) {
+    my ($k,$rum,$shot) = @_;
+    pr2($k,
+       valid($rum) ? sprintf("%12.1f fine equiv", $rum) : '',
+       valid($shot) ? sprintf("%10d shot", $shot) : '');
+}
 
 
-#    if (defined $price{Swill}) {
-#      map { $price{$_}= undef if $price{$_} eq 'x' } @rums;
-#    }
-#    if (defined $have{Swill}) {
-#      $have_proof= 0;
-#      map { $have_proof += $have{$_} * $proof{$_} } @rums;
-#    }
+sub compute_restock_requirements () {
+    return unless @want;
+    
+    my $rum_want= rum_total(@want);
 
 
-our ($best);
+    my $stocks= @have ? $have[-1] : [qw(0 0 0 0)];
+    my $rum_have= rum_total(@$stocks);
+    
+    pr2rs('desired stock level', $rum_want, $want[3]);
 
 
-our $have_proof;
+    my $rum_need = $rum_want - $rum_have;
+    my $shot_need = $want[3] - $stocks->[3];
 
 
-our ($need_proof, %need, %buy);
+    if (@have) {
+       pr2rs('current stock', $rum_have, $stocks->[3]);
+       pr2rs('restock requirement', $rum_need, $shot_need);
+       print "\n";
+    }
 
 
-sub compute_restock_requirements () {
-    if ($ship =~ m/^\d+/) {
-       $need{Fine} = $ship;
-    } else {
-       $ship =~ y/_/ /;
-       open F, "/home/ian/private/puzzle-pirates" or die $!;
-       my $this_ship= 0;
-       my $the_ship;
-       while (<F>) {
-           if (!m/\S/ || m/^\s*\#/) {
-               $this_ship= 0;
-               next;
-           }
-           if (!m/^\@/) {
-               next;
-           }
-           if (m/^\@(( [A-Z][-a-z]+){2,})\s*$/) {
-               $this_ship= (uc $1 eq uc " $ship" or
-                            uc $+ eq uc " $ship");
-               $the_ship= $1;
-               next;
+    if (@price) {
+       my ($rum_buy,$shot_buy) = ('','');
+       my ($rum_bill,$shot_bill) = qw(0 0);
+       my $ok=1;
+       if ($rum_need > 0) {
+           if (defined $best) {
+               my $rum_qty= $rum_need * 100 / $proofs[$best];
+               $rum_qty= ceil($rum_qty);
+               $rum_buy= sprintf('%12s %-11s  ',
+                                 "** $rum_qty","$kinds[$best] **");
+               $rum_bill= $rum_qty * $price[$best];
+           } else {
+               $rum_buy= '   (rum unavailable)';
+               $ok= 0;
            }
            }
-           next unless $this_ship;
-           if (m/^\@\s+(\d+)\s+fine\s*/) {
-               $need{Fine} = $1;
-               last;
+       }
+       if ($shot_need > 0) {
+           if (valid($price[3])) {
+               $shot_buy= sprintf('%7s shot **', "** $shot_need");
+               $shot_bill= $shot_need * $price[3];
+           } else {
+               $shot_buy= '  (shot unavailable)';
+               $ok= 0;
            }
        }
            }
        }
-       die $! if F->error;
-       die "unknown ship $ship" unless defined $need{Fine};
-       if (defined $ship) {
-           pr1("vessel",$the_ship);
+       if (length($rum_buy) or length($shot_buy)) {
+           pr2($ok
+               ? sprintf('for a total of %d poe', $rum_bill + $shot_bill)
+               : 'for',
+               $rum_bill ? sprintf("%12d poe       ", $rum_bill) : '',
+               $shot_bill ? sprintf("%10d poe", $shot_bill) : '');
+           pr2('BUY', $rum_buy, $shot_buy);
+       } else {
+           print "stocks are sufficient.\n";
        }
        }
+       print "\n";
     }
     }
-
-    pr1('desired stock level', sprintf("%4d fine rum", $need{Fine}));
-    $need_proof= $need{Fine} * $proof{Fine} - $have_proof;
-    map {
-       $buy{$_} = $need_proof / $proof{$_};
-    } @rums;
-    pr1("stock equivalent", sprintf "$ff fine rum", $have_proof / $proof{Fine});
-    pr1("restock equivalent", sprintf "$ff fine rum", $need_proof / $proof{Fine});
-    prf('would need', %buy, 'rum');
 }
 
 }
 
-sub compute_restock_cheapest_rum() {
-    my %bill;
-    map {
-       $bill{$_} = $buy{$_} * $price{$_} if defined $price{$_};
-    } @rums;
-    prf('nominal bill', %bill, 'poe');
-    print "\n";
-    if ($need_proof < 0) {
-       printf "stocks are sufficient";
-    } else {
-       my $buy= ceil($buy{$best});
-       printf "buy %d %s at %d poe each for %d poe",
-           $buy, $best, $price{$best}, $buy * $price{$best};
-    }
-    print "\n\n";
-}
+parse_args();
+print_inputs();
+compute_cheapest_rum();
+compute_stock_values();
+compute_restock_requirements();
 
 
-main();
+STDOUT->error and die $!;
+close STDOUT or die $!;