chiark / gitweb /
Allow %age adjustments to capacity
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Thu, 10 Sep 2009 00:52:40 +0000 (01:52 +0100)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Thu, 10 Sep 2009 00:52:40 +0000 (01:52 +0100)
yarrg/web/check_capacitystring
yarrg/web/docs

index ae1dec4..f001c79 100644 (file)
@@ -87,6 +87,19 @@ print STDERR "PAN \`$string'\n";
        return @mve;
 };
 
+my @mv_names= qw(mass volume);
+my $canon_numeric= $h->{'canon_numeric'}= sub {
+       print STDERR "CANNUM @_\n";
+       my $sep= '';
+       my $out= '';
+       foreach my $ix (qw(0 1)) {
+               next unless defined $_[$ix];
+               $out .= $sep; $sep= ' ';
+               $out .= sprintf "%g%s", $_[$ix], (qw(kg l))[$ix];
+       }
+       return $out;
+};
+
 $h->{'deltas'}= [ ];
 print STDERR "NDELTA0 $#{ $h->{'deltas'} }\n";
 
@@ -96,9 +109,29 @@ while (m/^(.*)(\bminus\b|-|\bplus\b|\+)/) {
        print STDERR "TERM L=\`$1' M=\`$2' R=\`$''\n";
        my ($signum,$signopstr)= 
                $2 =~ m/^p|^\+/ ? (+1,'plus') : (-1,'minus');
-       my (@mve)= $parse_numeric->($rhs, 0);
-       ${ $h->{Emsg} }= $mve[2] if defined $mve[2];
-       unshift @{ $h->{'deltas'} }, [ @mve,$signum,$signopstr ];
+       my @mveco;
+       if ($rhs =~ m/^\s*(\d{1,2}(?:\.\d{0,4})?)\%\s*$/) {
+               my $pct= 100.0 + $signum * $1;
+               @mveco= ($pct,$pct,undef);
+               push @mveco, sprintf "%s %g%%", $signopstr, $1;
+               push @mveco, sub {
+                       return undef unless defined $_[0];
+                       $_[0] * $_[1] / 100.0
+               };
+       } else {
+               @mveco= $parse_numeric->($rhs, 0);
+               if (!defined $mveco[2]) {
+                       push @mveco, $signopstr.' '.$canon_numeric->(@mveco);
+                       push @mveco, sub {
+                               ${ $h->{Emsg} }= "Cannot add or subtract".
+                                       " mass to/from volume"
+                                       unless defined $_[0];
+                               $_[0] + $_[1] * $signum
+                       };
+               }
+       }
+       ${ $h->{Emsg} }= $mveco[2] if defined $mveco[2];
+       unshift @{ $h->{'deltas'} }, [ @mveco ];
        print STDERR "NDELTA $#{ $h->{'deltas'} }\n";
        $_= $lhs;
 }
@@ -143,30 +176,19 @@ $h
 </%args>
 <%perl>
 
-return if length ${ $h->{Emsg} };
-
-my @mv_names= qw(mass volume);
+my $canon_numeric= $h->{'canon_numeric'};
 
-my $canon_numeric= sub {
-       print STDERR "CANNUM @_\n";
-       my $sep= '';
-       my $out= '';
-       foreach my $ix (qw(0 1)) {
-               next unless defined $_[$ix];
-               $out .= $sep; $sep= ' ';
-               $out .= sprintf "%g%s", $_[$ix], (qw(kg l))[$ix];
-       }
-       return $out;
-};
+return if length ${ $h->{Emsg} };
 
 my @mv;
+my @mv_names= qw(mass volume);
 if (@{ $h->{Specs} }) {
        @mv= @{ $h->{Results}[0] }[1,2];
-       print STDERR "INITIAL VESSEL @mv\n";
 } else {
        @mv= @{ $h->{'initial'} };
        ${ $h->{Canon} }= $canon_numeric->(@mv);
 }
+print STDERR "INITIAL @mv\n";
 
 print STDERR "NDELTAE $#{ $h->{'deltas'} }\n";
 foreach my $delta (@{ $h->{'deltas'} }) {
@@ -175,14 +197,10 @@ foreach my $delta (@{ $h->{'deltas'} }) {
        foreach my $ix (qw(0 1)) {
                next unless defined $delta->[$ix];
                print STDERR "DELTA I $ix\n";
-               if (!defined $mv[$ix]) {
-                       ${ $h->{Emsg} }= "Cannot add or subtract".
-                               " $mv_names[$ix] to/from $mv_names[!$ix]";
-                       return;
-               }
-               $mv[$ix] += $delta->[$ix] * $delta->[3];
+               $mv[$ix] = $delta->[4]->($mv[$ix], $delta->[$ix]);
+               return if length ${ $h->{Emsg} };
        }
-       ${ $h->{Canon} }.= " $delta->[4] ". $canon_numeric->(@$delta);
+       ${ $h->{Canon} }.= ' '.$delta->[3];
 }
 
 if (@{ $h->{Specs} } || @{ $h->{'deltas'} }) {
index 24d9f16..48a0062 100755 (executable)
@@ -114,23 +114,30 @@ So you should specify your vessel capacity.  You can enter things
 like:
 <dl>
 <dt>sloop
-<dd>The capacity of a sloop, exactly
+<dd>The capacity of a sloop, leaving no allowance for rum and shot
+<dt>sloop - 1%
+<dd>The capacity of a sloop minus 1%
 <dt>20t 13kl
-<dd>20 tonnes (20,000kg), 13 kilolitres (13,000l)
+<dd>13 tonnes (13,000kg), 20 kilolitres (20,000l)
 <dt>sloop - 100l 100kg
 <dd>The capacity of a sloop minus 100l, minus 100kg
 <dt>2t plus 500kg minus 200kg
 <dd>2300kg, with no limit on volume
 </dl>
+Evaluation is strictly from left to right.
+
+<p>
 
 Formally, the capacity is a list of terms, all but the first preceded
 by one of <kbd>-</kbd>, <kbd>minus</kbd>, <kbd>+</kbd>,
 <kbd>plus</kbd>.  Each term may specify a mass and/or a volume
 (separated by a space), as a number followed (without an intervening
 space) by a unit (<kbd>t</kbd>, <kbd>kg</kbd>, <kbd>kl</kbd> or
-<kbd>l</kbd>).  The first term may be a ship name or abbrevation
-instead.  If the first term specifies only one of mass or volume, all
-the subsequent terms may only adjust that same value.
+<kbd>l</kbd>).  Alternatively each term except the first may specify a
+percentage, which is applied as a percentage change to the answer from
+all the preceding terms.  The first term may be a ship name or
+abbrevation instead.  If the first term specifies only one of mass or
+volume, all the subsequent terms may only adjust that same value.
 
 <h3>Expected losses</h3>