Merge pull request #3019 from duckduckgo/mintsoft/conversions/plurals
Conversions: Harmonise unit definitionsmaster
commit
3a0e90fb62
|
@ -8,6 +8,7 @@ with 'DDG::GoodieRole::NumberStyler';
|
|||
use Math::Round qw/nearest/;
|
||||
use utf8;
|
||||
use YAML::XS 'LoadFile';
|
||||
use List::Util qw(any);
|
||||
|
||||
zci answer_type => 'conversions';
|
||||
zci is_cached => 1;
|
||||
|
@ -16,10 +17,15 @@ use bignum;
|
|||
|
||||
my @types = LoadFile(share('ratios.yml'));
|
||||
|
||||
my %unit_to_plural = ();
|
||||
my @units = ();
|
||||
my %plural_to_unit = ();
|
||||
foreach my $type (@types) {
|
||||
push(@units, $type->{'unit'});
|
||||
push(@units, $type->{'plural'}) unless lc $type->{'unit'} eq lc $type->{'plural'};
|
||||
push(@units, @{$type->{'aliases'}});
|
||||
$unit_to_plural{lc $type->{'unit'}} = $type->{'plural'};
|
||||
$plural_to_unit{lc $type->{'plural'}} = $type->{'unit'};
|
||||
}
|
||||
|
||||
# build triggers based on available conversion units:
|
||||
|
@ -35,33 +41,6 @@ my $question_prefix = qr/(?<prefix>convert|what (?:is|are|does)|how (?:much|many
|
|||
my $factor_re = join('|', ('a', 'an', number_style_regex()));
|
||||
my $guard = qr/^(?<question>$question_prefix)\s?(?<left_num>$factor_re*)\s?(?<left_unit>$keys)\s(?<connecting_word>in|to|into|(?:in to)|from)?\s?(?<right_num>$factor_re*)\s?(?:of\s)?(?<right_unit>$keys)[\?]?$/i;
|
||||
|
||||
# exceptions for pluralized forms:
|
||||
my %plural_exceptions = (
|
||||
'stone' => 'stone',
|
||||
'foot' => 'feet',
|
||||
'inch' => 'inches',
|
||||
'pounds per square inch' => 'pounds per square inch',
|
||||
'ton of TNT' => 'tons of TNT',
|
||||
'metric horsepower' => 'metric horsepower',
|
||||
'horsepower' => 'horsepower',
|
||||
'electrical horsepower' => 'electrical horsepower',
|
||||
'pounds force' => 'pounds force',
|
||||
'坪' => '坪',
|
||||
'km/h' => 'km/h',
|
||||
'mph' => 'mph',
|
||||
'm/s' => 'm/s',
|
||||
'ft/s' => 'ft/s',
|
||||
'dram avoirdupois' => 'drams avoirdupois',
|
||||
'thousandth of an inch' => 'thousandths of an inch',
|
||||
'century' => 'centuries',
|
||||
'millennium' => 'millennia',
|
||||
'mmHg' => 'mmHg',
|
||||
'torr' => 'torr',
|
||||
'cubic inch' => 'cubic inches',
|
||||
'square foot' => 'square feet'
|
||||
);
|
||||
my %singular_exceptions = reverse %plural_exceptions;
|
||||
|
||||
# fix precision and rounding:
|
||||
my $precision = 3;
|
||||
my $nearest = '.' . ('0' x ($precision-1)) . '1';
|
||||
|
@ -133,8 +112,7 @@ handle query_lc => sub {
|
|||
&& "" eq $+{'right_num'}
|
||||
&& $+{'question'} !~ qr/convert/i
|
||||
&& !looks_plural($+{'right_unit'})
|
||||
&& $+{'connecting_word'} !~ qr/to/i
|
||||
&& $factor1[0] > $factor2[0]))
|
||||
&& $+{'connecting_word'} !~ qr/to/i ))
|
||||
{
|
||||
$factor = $+{'right_num'};
|
||||
@matches = ($matches[1], $matches[0]);
|
||||
|
@ -194,31 +172,31 @@ handle query_lc => sub {
|
|||
};
|
||||
$factor = $styler->for_display($factor);
|
||||
|
||||
return $factor . " $result->{'from_unit'} = $result->{'result'} $result->{'to_unit'}",
|
||||
structured_answer => {
|
||||
data => {
|
||||
raw_input => $styler->for_computation($factor),
|
||||
raw_answer => $styler->for_computation($result->{'result'}),
|
||||
left_unit => $result->{'from_unit'},
|
||||
right_unit => $result->{'to_unit'},
|
||||
markup_input => $styler->with_html($factor),
|
||||
styled_output => $styler->with_html($result->{'result'}),
|
||||
physical_quantity => $result->{'type'}
|
||||
},
|
||||
templates => {
|
||||
group => 'text',
|
||||
options => {
|
||||
content => 'DDH.conversions.content'
|
||||
}
|
||||
}
|
||||
return "$factor $result->{'from_unit'} = $result->{'result'} $result->{'to_unit'}",
|
||||
structured_answer => {
|
||||
data => {
|
||||
raw_input => $styler->for_computation($factor),
|
||||
raw_answer => $styler->for_computation($result->{'result'}),
|
||||
left_unit => $result->{'from_unit'},
|
||||
right_unit => $result->{'to_unit'},
|
||||
markup_input => $styler->with_html($factor),
|
||||
styled_output => $styler->with_html($result->{'result'}),
|
||||
physical_quantity => $result->{'type'}
|
||||
},
|
||||
templates => {
|
||||
group => 'text',
|
||||
options => {
|
||||
content => 'DDH.conversions.content'
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
sub looks_plural {
|
||||
my ($unit) = @_;
|
||||
my @unit_letters = split //, $unit;
|
||||
return exists $singular_exceptions{$unit} || $unit_letters[-1] eq 's';
|
||||
my ($input) = @_;
|
||||
return defined $plural_to_unit{lc $input};
|
||||
}
|
||||
|
||||
sub convert_temperatures {
|
||||
my ($from, $to, $in_temperature) = @_;
|
||||
|
||||
|
@ -244,11 +222,10 @@ sub convert_temperatures {
|
|||
}
|
||||
sub get_matches {
|
||||
my @input_matches = @_;
|
||||
|
||||
my @output_matches = ();
|
||||
foreach my $match (@input_matches) {
|
||||
foreach my $type (@types) {
|
||||
if (lc $match eq $type->{'unit'} || grep { $_ eq lc $match } @{$type->{'aliases'}}) {
|
||||
if (lc $match eq $type->{'unit'} || lc $match eq lc $type->{'plural'} || grep { $_ eq lc $match } @{$type->{'aliases'}}) {
|
||||
push(@output_matches,{
|
||||
type => $type->{'type'},
|
||||
factor => $type->{'factor'},
|
||||
|
@ -267,6 +244,7 @@ sub convert {
|
|||
my @matches = get_matches($conversion->{'from_unit'}, $conversion->{'to_unit'});
|
||||
|
||||
return if $conversion->{'factor'} < 0 && !($matches[0]->{'can_be_negative'});
|
||||
|
||||
# matches must be of the same type (e.g., can't convert mass to length):
|
||||
return if ($matches[0]->{'type'} ne $matches[1]->{'type'});
|
||||
|
||||
|
@ -286,19 +264,11 @@ sub convert {
|
|||
"type" => $matches[0]->{'type'}
|
||||
};
|
||||
}
|
||||
|
||||
sub set_unit_pluralisation {
|
||||
my ($unit, $count) = @_;
|
||||
my $proper_unit = $unit;
|
||||
|
||||
my $already_plural = looks_plural($unit);
|
||||
|
||||
if ($already_plural && $count == 1) {
|
||||
$proper_unit = $singular_exceptions{$unit} || substr($unit, 0, -1);
|
||||
} elsif (!$already_plural && $count != 1) {
|
||||
$proper_unit = $plural_exceptions{$unit} || $unit . 's';
|
||||
}
|
||||
|
||||
return $proper_unit;
|
||||
$unit = $unit_to_plural{lc $unit} if ($count != 1 && !looks_plural($unit));
|
||||
return $unit;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -359,6 +359,18 @@ ddg_goodie_test(
|
|||
physical_quantity => 'pressure'
|
||||
})
|
||||
),
|
||||
'0.01933677566613741911668448550544 psi in mmHg' => test_zci(
|
||||
'0.01933677566613741911668448550544 pounds per square inch = 1 mmHg',
|
||||
structured_answer => make_answer({
|
||||
markup_input => '0.01933677566613741911668448550544',
|
||||
raw_input => '0.01933677566613741911668448550544',
|
||||
from_unit => 'pounds per square inch',
|
||||
styled_output => '1',
|
||||
raw_answer => '1',
|
||||
to_unit => 'mmHg',
|
||||
physical_quantity => 'pressure'
|
||||
})
|
||||
),
|
||||
'2 thou to mm' => test_zci(
|
||||
'2 thousandths of an inch = 0.051 millimeters',
|
||||
structured_answer => make_answer({
|
||||
|
@ -599,6 +611,18 @@ ddg_goodie_test(
|
|||
physical_quantity => 'energy'
|
||||
})
|
||||
),
|
||||
'1000000 kcal in tons of tnt' => test_zci(
|
||||
'1,000,000 large calories = 1 ton of TNT',
|
||||
structured_answer => make_answer({
|
||||
markup_input => '1,000,000',
|
||||
raw_input => '1000000',
|
||||
from_unit => 'large calories',
|
||||
styled_output => '1',
|
||||
raw_answer => '1',
|
||||
to_unit => 'ton of TNT',
|
||||
physical_quantity => 'energy'
|
||||
})
|
||||
),
|
||||
'90 ps in watts' => test_zci(
|
||||
'90 metric horsepower = 66,194.888 watts',
|
||||
structured_answer => make_answer({
|
||||
|
@ -984,14 +1008,14 @@ ddg_goodie_test(
|
|||
})
|
||||
),
|
||||
'ml in gallons' => test_zci(
|
||||
'1 millilitre = 0.000264 us gallons',
|
||||
'1 us gallon = 3,785.412 millilitres',,
|
||||
structured_answer => make_answer({
|
||||
markup_input => '1',
|
||||
raw_input => '1',
|
||||
from_unit => 'millilitre',
|
||||
styled_output => '0.000264',
|
||||
raw_answer => '0.000264',
|
||||
to_unit => 'us gallons',
|
||||
from_unit => 'us gallon',
|
||||
styled_output => '3,785.412',
|
||||
raw_answer => '3785.412',
|
||||
to_unit => 'millilitres',
|
||||
physical_quantity => 'volume'
|
||||
})
|
||||
),
|
||||
|
@ -1431,14 +1455,14 @@ ddg_goodie_test(
|
|||
})
|
||||
),
|
||||
'how many cm in metres?' => test_zci(
|
||||
'1 centimeter = 0.010 meters',
|
||||
'1 meter = 100 centimeters',
|
||||
structured_answer => make_answer({
|
||||
markup_input => '1',
|
||||
raw_input => '1',
|
||||
from_unit => 'centimeter',
|
||||
styled_output => '0.010',
|
||||
raw_answer => '0.010',
|
||||
to_unit => 'meters',
|
||||
from_unit => 'meter',
|
||||
styled_output => '100',
|
||||
raw_answer => '100',
|
||||
to_unit => 'centimeters',
|
||||
physical_quantity => 'length'
|
||||
})
|
||||
),
|
||||
|
|
Loading…
Reference in New Issue