X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~yarrgweb/git?p=ypp-sc-tools.db-live.git;a=blobdiff_plain;f=yarrg%2Fweb%2Fcheck_capacitystring;fp=yarrg%2Fweb%2Fcheck_capacitystring;h=ae1dec45b879e98c2fa302368d08115b24aef60c;hp=3d8f7a52701fd2983c09ca6bdc6629af1467ec91;hb=03d941b69511108bea1a2a20486f36e55c94d848;hpb=5b88fe0fb309a1d55292c6b10b967481b78440d7 diff --git a/yarrg/web/check_capacitystring b/yarrg/web/check_capacitystring index 3d8f7a5..ae1dec4 100644 --- a/yarrg/web/check_capacitystring +++ b/yarrg/web/check_capacitystring @@ -34,6 +34,7 @@ <%attr> +maxambig => 2 <%method preparse> @@ -42,47 +43,161 @@ $h <%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]; } + +<%method sqlstmt> +SELECT name,mass,volume + FROM vessels WHERE name LIKE ? + + +<%method nomatch> + Did not understand ship name. + + +<%method ambiguous> + Ambiguous - could be <% $ARGS{couldbe} |h %> + + +<%method manyambig> + Too many matching ship types. + + <%method postquery> <%args> $h <%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 ]; +