</%doc>
<%attr>
+maxambig => 2
</%attr>
<%method preparse>
</%args>
<%perl>
-my $def= sub {
- my ($what,$val) = @_;
- if (defined $h->{$what}) {
- $h->{Emsg}= "Multiple definitions of maximum $what.";
+my $parse_numeric= sub {
+ # returns (mass,volume,emsg)
+ my ($string,$default)= @_;
+
+ my @mve= (undef,undef,undef);
+
+ if ($string !~ m/\d/) {
+ return (undef,undef,
+ 'Adjustments to capacity must contain digits.');
}
- print STDERR "SET $what $val\n";
- $h->{$what}= $val;
-};
-foreach $_ (split /\s+/, ${ $h->{String} }) {
- print STDERR "ITEM \`$_'\n";
- next unless length;
- if (m/^([1-9]\d{0,8})l$/) {
- $def->('volume', $1);
- } elsif (m/^([1-9]\d{0,8})kg$/) {
- $def->('mass', $1);
- } elsif (m/^([1-9]\d{0,5}(?:\.\d{0,3})?)kl/) {
- $def->('volume', $1 * 1000);
- } elsif (m/^([1-9]\d{0,5}(?:\.\d{0,3})?)t/) {
- $def->('mass', $1 * 1000);
- } else {
- ${ $h->{Emsg} }= "Cannot understand capacity \`$_'.";
- last;
+ my $def= sub {
+ my ($ix,$what,$val) = @_;
+ if (defined $h->{$what}) {
+ $mve[2]= "\`$string' specifies $what more than once.";
+ }
+ print STDERR "SET $what $val\n";
+ $mve[$ix]= $val;
+ };
+
+print STDERR "PAN \`$string'\n";
+ local $_;
+ foreach $_ (split /\s+/, $string) {
+ print STDERR "ITEM \`$_'\n";
+ next unless length;
+ if (m/^([1-9]\d{0,8})l$/) {
+ $def->(1, 'volume', $1);
+ } elsif (m/^([1-9]\d{0,8})kg$/) {
+ $def->(0, 'mass', $1);
+ } elsif (m/^([1-9]\d{0,5}(?:\.\d{0,3})?)kl/) {
+ $def->(1, 'volume', $1 * 1000);
+ } elsif (m/^([1-9]\d{0,5}(?:\.\d{0,3})?)t/) {
+ $def->(0, 'mass', $1 * 1000);
+ } else {
+ $mve[2]= "Cannot understand item \`$_'".
+ " in numeric capacity";
+ }
}
+# foreach my $ix (qw(0 1)) {
+# $mve[$ix]= $default unless defined $mve[$ix];
+# }
+ return @mve;
+};
+
+$h->{'deltas'}= [ ];
+print STDERR "NDELTA0 $#{ $h->{'deltas'} }\n";
+
+local ($_)= ${ $h->{String} };
+while (m/^(.*)(\bminus\b|-|\bplus\b|\+)/) {
+ my ($lhs,$rhs)= ($1,$');
+ 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 ];
+ print STDERR "NDELTA $#{ $h->{'deltas'} }\n";
+ $_= $lhs;
+}
+
+s/^\s+//; s/\s+$//;
+
+if (m/^[a-z ]+$/) {
+ push @{ $h->{Specs} }, $_;
+} elsif (m/\d/) {
+ my (@mve)= $parse_numeric->($_, undef);
+ if (defined $mve[2]) { ${ $h->{Emsg} }= $mve[2]; return; }
+ $h->{'initial'}= \@mve;
+} elsif (m/\S/) {
+ ${ $h->{Emsg} }= "Cannot understand capacity specification \`$_'.";
+} else {
+ $h->{'initial'}= [undef,undef];
}
+
</%perl>
</%method>
+<%method sqlstmt>
+SELECT name,mass,volume
+ FROM vessels WHERE name LIKE ?
+</%method>
+
+<%method nomatch>
+ Did not understand ship name.
+</%method>
+
+<%method ambiguous>
+ Ambiguous - could be <% $ARGS{couldbe} |h %>
+</%method>
+
+<%method manyambig>
+ Too many matching ship types.
+</%method>
+
<%method postquery>
<%args>
$h
</%args>
<%perl>
-if (defined $h->{'mass'} or defined $h->{'volume'}) {
- @{ $h->{Results} } = [ $h->{'mass'}, $h->{'volume'} ];
+return if length ${ $h->{Emsg} };
+
+my @mv_names= qw(mass volume);
+
+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;
+};
+
+my @mv;
+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 "NDELTAE $#{ $h->{'deltas'} }\n";
+foreach my $delta (@{ $h->{'deltas'} }) {
+ print STDERR "DELTA @$delta\n";
+ die if defined $delta->[2]; # emsg
+ 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];
+ }
+ ${ $h->{Canon} }.= " $delta->[4] ". $canon_numeric->(@$delta);
+}
- ${ $h->{Canon} }=
- 'mass limit: '.(defined $h->{'mass'} ? $h->{'mass'} .'kg' : 'none').'; '.
- 'volume limit: '.(defined $h->{'volume'} ? $h->{'volume'} .'l' : 'none').'.';
+if (@{ $h->{Specs} } || @{ $h->{'deltas'} }) {
+ ${ $h->{Canon} }.= " [= ". $canon_numeric->(@mv). "]";
}
+foreach my $ix (qw(0 1)) {
+ next unless defined $mv[$ix];
+ next if $mv[$ix] >= 0;
+ ${ $h->{Emsg} }= sprintf "%s limit is negative: %s",
+ ucfirst($mv_names[$ix]), $canon_numeric->(@mv);
+ return;
+}
+
+@{ $h->{Results} }= [ @mv ];
+
</%perl>
</%method>