Merge branch 'pjhampton/conversion-add_interactivity'

* pjhampton/conversion-add_interactivity: (72 commits)
  Flip top and bottom section, minor design tweaks remove left padding to aling selection with search box widen unit dropdown width to allow for long unit names
  Removed mathjs import in node context.
  Comment out math import.
  Travis... please work.
  Add mathjs to travis.
  Add tests for custom units.
  Add math for tests.
  Order select keys alphabetically.
  Checking in work.
  Update triggers.
  Fixed digital triggering.
  Update reconvert logic.
  Update 'update' side
  Add comments. General refactor.
  Add support for digital units.
  Whoops, force height on select not frm__select
  Force select height, override .frm__select class
  remove border radius for conversion inputs too
  Code clean up. Some quick wins.
  Support custom energy funcs.
  ...
master
Zaahir Moolla 2017-05-03 15:42:06 -04:00
commit 6309e550a2
10 changed files with 3119 additions and 5228 deletions

View File

@ -16,7 +16,7 @@ before_install:
- git config --global user.name "Dist Zilla Plugin TravisCI"
- git config --global user.email $HOSTNAME":not-for-mail@travis-ci.org"
install:
- npm install -g uglify-js handlebars jasmine
- npm install -g uglify-js handlebars mathjs jasmine
- cpanm --quiet --notest Dist::Zilla
- dzil authordeps | grep -ve '^\W' | xargs -n 5 -P 10 cpanm --quiet --notest --mirror http://www.cpan.org/ --mirror http://duckpan.org
- dzil listdeps | grep -ve '^\W' | cpanm --quiet --notest --mirror http://www.cpan.org/ --mirror http://duckpan.org

View File

@ -1,5 +1,5 @@
package DDG::Goodie::Conversions;
# ABSTRACT: convert between various units of measurement
# ABSTRACT: Handles triggering and preprocessing for the Conversions IA
use strict;
use DDG::Goodie;
@ -16,25 +16,22 @@ zci is_cached => 1;
use bignum;
my @types = LoadFile(share('ratios.yml'));
my @types = LoadFile(share('triggers.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'}});
push(@units, @{$type->{'symbols'}}) if $type->{'symbols'};
$unit_to_plural{lc $type->{'unit'}} = $type->{'plural'};
$plural_to_unit{lc $type->{'plural'}} = $type->{'unit'};
}
# build triggers based on available conversion units:
my @triggers = map { lc $_ } @units;
triggers any => @triggers;
my @lang_triggers = ('online converter', 'online conversion', 'unit converter', 'unit conversion');
triggers any => @lang_triggers;
# match longest possible key (some keys are sub-keys of other keys):
my $keys = join '|', map { quotemeta $_ } reverse sort { length($a) <=> length($b) } @units;
my $question_prefix = qr/(?<prefix>convert|what (?:is|are|does)|how (?:much|many|long) (?:is|are)?|(?:number of)|(?:how to convert)|(?:convert from))?/i;
@ -60,10 +57,23 @@ sub magnitude_order {
my $maximum_input = 10**100;
handle query => sub {
# for natural language queries, settle with default template / data
if ( $_ ~~ @lang_triggers ) {
return '', structured_answer => {
data => {},
templates => {
group => 'base',
options => {
content => 'DDH.conversions.content'
}
}
};
}
# hack around issues with feet and inches for now
$_ =~ s/"/inches/;
$_ =~ s/'/feet/;
$_ =~ s/"/inch/;
$_ =~ s/'/foot/;
if($_ =~ /(\d+)\s*(?:feet|foot)\s*(\d+)(?:\s*inch(?:es)?)?/i){
my $feetHack = $1 + $2/12;
@ -122,7 +132,6 @@ handle query => sub {
|| ( "" eq $+{'left_num'}
&& "" eq $+{'right_num'}
&& $+{'question'} !~ qr/convert/i
&& !looks_plural($+{'right_unit'})
&& $+{'connecting_word'} !~ qr/to/i ))
{
$factor = $+{'right_num'};
@ -143,56 +152,18 @@ handle query => sub {
return unless defined $result->{'result'};
my $formatted_result = sprintf("%.${accuracy}f", $result->{'result'});
$formatted_result = FormatSigFigs($result->{'result'}, $accuracy) if abs($result->{'result'}) < 1;
# if $result = 1.00000 .. 000n, where n <> 0 then $result != 1 and throws off pluralization, so:
$result->{'result'} = nearest($nearest, $result->{'result'});
if ($result->{'result'} == 0 || magnitude_order($result->{result}) >= 2*$accuracy + 1) {
# rounding error
$result = convert({
'factor' => $styler->for_computation($factor),
'from_unit' => $matches[0],
'to_unit' => $matches[1],
}) or return;
# We only display it in exponent form if it's above a certain number.
# We also want to display numbers from 0 to 1 in exponent form.
if($result->{'result'} > 9_999_999 || abs($result->{'result'}) < 1) {
$formatted_result = (sprintf "%.${scientific_notation_sig_figs}g", $result->{'result'});
}
}
# handle pluralisation of units
# however temperature is never plural and does require "degrees" to be prepended
if ($result->{'type'} eq 'temperature') {
$result->{'from_unit'} = ($factor == 1 ? "degree" : "degrees") . " $result->{'from_unit'}" if ($result->{'from_unit'} ne "kelvin");
$result->{'to_unit'} = ($result->{'result'} == 1 ? "degree" : "degrees") . " $result->{'to_unit'}" if ($result->{'to_unit'} ne "kelvin");
} else {
$result->{'from_unit'} = set_unit_pluralisation($result->{'from_unit'}, $factor);
$result->{'to_unit'} = set_unit_pluralisation($result->{'to_unit'}, $result->{'result'});
}
$result->{'result'} = $formatted_result;
$result->{'result'} =~ s/\.0{$accuracy}$//;
$result->{'result'} = $styler->for_display($result->{'result'});
# TODO: it's not clear what this does exactly. Come back and comment
my $computable_factor = $styler->for_computation($factor);
if (magnitude_order($computable_factor) > 2*$accuracy + 1) {
$factor = sprintf('%g', $computable_factor);
};
$factor = $styler->for_display($factor);
return "$factor $result->{'from_unit'} = $result->{'result'} $result->{'to_unit'}",
structured_answer => {
return "", 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 => {
@ -204,34 +175,6 @@ handle query => sub {
};
};
sub looks_plural {
my ($input) = @_;
return defined $plural_to_unit{lc $input};
}
sub convert_temperatures {
my ($from, $to, $in_temperature) = @_;
my $kelvin;
# Convert to SI (Kelvin)
if ($from =~ /^f(?:ahrenheit)?$/i) { $kelvin = ($in_temperature + 459.67) * 5/9; }
elsif ($from =~ /^c(?:elsius)?$/i) { $kelvin = $in_temperature + 273.15; }
elsif ($from =~ /^k(?:elvin)?$/i) { $kelvin = $in_temperature; }
elsif ($from =~ /^r(?:ankine)?$/i) { $kelvin = $in_temperature * 5/9; }
elsif ($from =~ /^reaumur$/i) { $kelvin = $in_temperature * 5/4 + 273.15 }
else { die; }
my $out_temperature;
# Convert to Target Unit
if ($to =~ /^f(?:ahrenheit)?$/i) { $out_temperature = $kelvin * 9/5 - 459.67; }
elsif ($to =~ /^c(?:elsius)?$/i) { $out_temperature = $kelvin - 273.15; }
elsif ($to =~ /^k(?:elvin)?$/i) { $out_temperature = $kelvin; }
elsif ($to =~ /^r(?:ankine)?$/i) { $out_temperature = $kelvin * 9/5; }
elsif ($to =~ /^reaumur$/i) { $out_temperature = ($kelvin - 273.15) * 4/5; }
else { die; }
return $out_temperature;
}
sub get_matches {
my @input_matches = @_;
my @output_matches = ();
@ -239,7 +182,6 @@ sub get_matches {
foreach my $type (@types) {
if (($type->{'symbols'} && grep { $_ eq $match } @{$type->{'symbols'}})
|| lc $match eq lc $type->{'unit'}
|| lc $match eq lc $type->{'plural'}
|| grep { $_ eq lc $match } @{$type->{'aliases'}} ) {
push(@output_matches,{
type => $type->{'type'},
@ -252,6 +194,7 @@ sub get_matches {
}
return @output_matches;
}
sub convert {
my ($conversion) = @_;
@ -262,27 +205,12 @@ sub convert {
# matches must be of the same type (e.g., can't convert mass to length):
return if ($matches[0]->{'type'} ne $matches[1]->{'type'});
my $result;
# run the conversion:
# temperatures don't have 1:1 conversions, so they get special treatment:
if ($matches[0]->{'type'} eq 'temperature') {
$result = convert_temperatures($matches[0]->{'unit'}, $matches[1]->{'unit'}, $conversion->{'factor'})
}
else {
$result = $conversion->{'factor'} * ($matches[1]->{'factor'} / $matches[0]->{'factor'});
}
return {
"result" => $result,
"result" => "",
"from_unit" => $matches[0]->{'unit'},
"to_unit" => $matches[1]->{'unit'},
"type" => $matches[0]->{'type'}
};
}
sub set_unit_pluralisation {
my ($unit, $count) = @_;
$unit = $unit_to_plural{lc $unit} if ($count != 1 && !looks_plural($unit));
return $unit;
}
1;

View File

@ -1,7 +1,25 @@
<div class='zci__conversions-controls'>
<h3 class='zci__caption zci__result'>{{{styled_output}}} {{right_unit}}</h3>
<h4 class='zci__subheader'>
<span class='zci__operation tx-clr--lt2'>Convert:</span>
<span class='zci__input'>{{{markup_input}}} {{left_unit}}</span>
</h4>
</div>
<!-- the bottom input section to change the unit type -->
<div class="frm frm--top">
<div class="frm__select">
<select class="frm__select--bottom"></select>
</div>
</div>
<!-- the left input section -->
<div class="frm frm--bottom clearfix">
<div class="input__wrap input__wrap--left shadow">
<input class="frm__input frm__input--left">
<div class="frm__select">
<select class="frm__select--left"></select>
</div>
</div>
<div class="equals-sign tx-clr--slate">=</div>
<div class="input__wrap input__wrap--right shadow">
<input class="frm__input frm__input--right">
<div class="frm__select">
<select class="frm__select--right"></select>
</div>
</div>
</div>

View File

@ -0,0 +1,100 @@
.zci--conversions .zci__body {
margin: 0;
box-sizing: border-box;
padding-left: 0;
}
.zci--conversions .shadow {
box-shadow: 1px 1px 5px 0px #e5e5e5;
}
.dark-bg .zci--conversions .shadow {
box-shadow: none;
}
.zci--conversions .frm--top .frm__select {
width: 100%;
}
.zci--conversions .frm--top .frm__select--bottom {
width: 100% !important;
}
.zci--conversions .frm--top {
margin-bottom: 1em;
}
.zci--conversions .frm--bottom > div {
float: left;
}
.zci--conversions .input__wrap {
width: 45%;
}
.zci--conversions .frm--bottom .frm__input,
.zci--conversions .frm--bottom .frm__select {
display: block;
float: left;
height: 3em;
line-height: 3;
padding: 0;
border-color: #c9c9c9;
font-weight: bold;
text-align: center;
}
.zci--conversions .frm--bottom .frm__input {
width: 50%;
border-right: none;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.zci--conversions .frm--bottom .frm__select {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
width: 50%;
border-left-color: #e0e0e0;
}
.zci--conversions .frm--bottom .frm__select select {
width: 100%;
height: 3em !important;
}
.zci--conversions .equals-sign {
width: 10%;
vertical-align: top;
text-align: center;
font-size: 2em;
line-height: 1.6;
}
/* Mobile */
.is-mobile .zci--conversions .frm--bottom .frm__input,
.is-mobile .zci--conversions .frm--bottom .frm__select {
display: block;
width: 100%;
height: 3em;
line-height: 3;
padding: 0;
font-weight: bold;
text-align: center;
}
.is-mobile .zci--conversions .frm--bottom .frm__input {
border-bottom: none;
border-right: 1px solid #c9c9c9;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.is-mobile .zci--conversions .frm--bottom .frm__select {
border-top-left-radius: 0;
border-top-right-radius: 0;
border-bottom-left-radius: 2px;
border-top-color: #e0e0e0;
border-left-color: #c9c9c9;
}

View File

@ -1,5 +1,449 @@
DDH.conversions = DDH.conversions || {};
DDH.conversions.build = function() {
return {};
};
(function(DDH) {
"use strict";
// flag variables for onShow functionality
var localDOMInitialized = false;
var initialized = false;
// UI: the input / output fields
var $convert_left,
$convert_right,
$select_right,
$select_left,
$unitSelector,
$selects;
// caches the local DOM vars
function setUpLocalDOM() {
var $root = DDH.getDOM('conversions');
$convert_left = $root.find(".frm__input--left");
$convert_right = $root.find(".frm__input--right");
$selects = $root.find(".frm--bottom select");
$select_right = $root.find(".frm__select--right");
$select_left = $root.find(".frm__select--left");
$unitSelector = $root.find(".frm__select--bottom");
localDOMInitialized = true;
}
/**
* Converter
*
* The converter object is responsible for getting the values from
* the UI and building the expression that is passed to the math object
*/
var Converter = {
// the local vars
leftUnit: "",
rightUnit: "",
leftValue: "",
rightValue: "",
// custom units that are not supported by math.js
setUpCustomUnits: function() {
// CUSTOM ENERGY UNITS
math.createUnit('kilojoule', '1000 joules');
math.createUnit('gramcalorie', '4.184 joules');
math.createUnit('kilocalorie', '4184 joules');
// CUSTOM DIGITAL UNITS
math.createUnit('kbit', '1000 b');
math.createUnit('mbit', '1000000 b');
math.createUnit('gbit', '1000000000 b');
math.createUnit('tbit', '1000000000000 b');
math.createUnit('KB', '1000 B');
math.createUnit('MB', '1000000 B');
math.createUnit('GB', '1000000000 B');
math.createUnit('TB', '1000 GB');
math.createUnit('PB', '1000 TB');
},
setValues: function() {
this.setLeftUnit();
this.setRightUnit();
this.setLeftValue();
this.setRightValue();
},
setLeftUnit: function() {
this.leftUnit = $select_left.val();
},
setLeftValue: function() {
this.leftValue = $convert_left.val();
},
setRightUnit: function() {
this.rightUnit = $select_right.val();
},
setRightValue: function() {
this.rightValue = $convert_right.val();
},
eval: function( expression ) {
return math.eval(expression).format({ precision: 6 }).split(" ")[0];
},
convert: function( side ) {
// if side isn't defined, default to right
var side = side || "right"
this.setValues();
if(side === "right") {
var expression = this.leftValue + " " + this.leftUnit + " to " + this.rightUnit;
$convert_right.val(this.eval(expression));
} else {
var expression = this.rightValue + " " + this.rightUnit + " to " + this.leftUnit;
$convert_left.val(this.eval(expression));
}
},
// removes all the options
emptySelects: function() {
$select_left.empty();
$select_right.empty();
},
updateUnitSelectors: function( key ) {
// resets the selects state
this.emptySelects();
// sort the keys alphabetically
Units[key].units.sort(function(a, b) {
var softA = a.name.toUpperCase();
var softB = b.name.toUpperCase();
return (softA < softB) ? -1 : (softA > softB) ? 1 : 0;
});
// adds the new conversion units to the selects
for(var i = 0 ; i < Units[key].units.length ; i++) {
$selects.append(
'<option value="' + Units[key].units[i].symbol + '">'
+ Units[key].units[i].name
+ '</option>'
);
}
// set defaults. these should match Units[key].units[i].symbol
$select_left.val(Units[key].defaults[0]);
$select_right.val(Units[key].defaults[1]);
},
// updates the list of bases to choose from. Should only be called once (on startup)
updateBaseUnitSelector: function( startBase ) {
// adds the different unit types to the selector
var unitKeys = Object.keys(Units);
$.each(unitKeys.sort(), function(_key, value) {
$unitSelector.append(
'<option value="'+value+'"' + (value === startBase ? " selected='selected'" : "") + '>'
+ Units[value].name
+ '</option>'
);
});
}
} // Converter
/**
* Units
*
* The bases and their units that we provide for the user
*/
var Units = {
angle: {
name: "Angle",
units: [
{ symbol: 'rad', name: 'Radians' },
{ symbol: 'deg', name: 'Degrees' },
{ symbol: 'grad', name: 'Gradians' },
{ symbol: 'cycle', name: 'Cycles' },
{ symbol: 'arcsec', name: 'Arcsecond' },
{ symbol: 'arcmin', name: 'Arcminute' },
{ symbol: 'millirad', name: 'Milliradian' },
],
defaults: ['deg', 'rad']
},
area: {
name: "Area",
units: [
{ symbol: 'm2', name: 'Square Meter' },
{ symbol: 'sqin', name: 'Square Inch' },
{ symbol: 'sqft', name: 'Square Feet' },
{ symbol: 'sqyd', name: 'Square Yard' },
{ symbol: 'sqmi', name: 'Square Mile' },
{ symbol: 'acre', name: 'Acre' },
{ symbol: 'hectare', name: 'Hectare' }
],
defaults: ['m2', 'sqin']
},
digital: {
name: "Digital Storage",
units: [
{ symbol: 'b', name: 'Bit' },
{ symbol: 'B', name: 'Byte' },
{ symbol: 'kbit', name: 'Kilobit' },
{ symbol: 'mbit', name: 'Megabit'},
{ symbol: 'gbit', name: 'Gigabit'},
{ symbol: 'tbit', name: 'Terrabit'},
{ symbol: 'KB', name: 'Kilobyte'},
{ symbol: 'MB', name: 'Megabyte'},
{ symbol: 'GB', name: 'Gigabyte'},
{ symbol: 'TB', name: 'Terabyte'},
{ symbol: 'PB', name: 'Petabyte'},
],
defaults: ['b', 'B']
},
duration: {
name: "Duration",
units: [
{ symbol: 'nanosecond', name: 'Nanoseconds' },
{ symbol: 'microsecond', name: 'Microseconds' },
{ symbol: 'millisecond', name: 'Milliseconds' },
{ symbol: 'second', name: 'Seconds' },
{ symbol: 'minute', name: 'Minutes' },
{ symbol: 'hour', name: 'Hours' },
{ symbol: 'day', name: 'Days' },
{ symbol: 'week', name: 'Weeks' },
{ symbol: 'month', name: 'Months'},
{ symbol: 'year', name: 'Years' },
{ symbol: 'decade', name: 'Decade' },
{ symbol: 'century', name: 'Century' },
{ symbol: 'millennium', name: 'Millennium' },
],
defaults: ['minute', 'second']
},
energy: {
name: "Energy",
units: [
{ symbol: 'joule', name: 'Joule' },
{ symbol: 'kilojoule', name: 'Kilojoule' },
{ symbol: 'gramcalorie', name: 'Gram Calorie'},
{ symbol: 'kilocalorie', name: 'Kilo Calorie'},
{ symbol: 'Wh', name: 'Watt Hour' },
{ symbol: 'erg', name: 'Erg' },
{ symbol: 'BTU', name: 'BTU'},
{ symbol: 'electronvolt', name: 'Electronvolt'},
],
defaults: ['joule', 'Wh']
},
force: {
name: "Force",
units: [
{ symbol: 'newton', name: 'Newton' },
{ symbol: 'dyne', name: 'Dyne'},
{ symbol: 'poundforce', name: 'Pound Force'},
{ symbol: 'kip', name: 'Kip'},
],
defaults: ['newton', 'dyne']
},
length: {
name: "Length",
units: [
{ symbol: 'decameter', name: 'Decameter' },
{ symbol: 'millimeter', name: 'Millimeter' },
{ symbol: 'micrometer', name: 'Micrometer' },
{ symbol: 'micrometer', name: 'Micrometer' },
{ symbol: 'nanometer', name: 'Nanometer' },
{ symbol: 'picometer', name: 'Picometer' },
{ symbol: 'kilometer', name: 'Kilometer' },
{ symbol: 'meter', name: 'Meter' },
{ symbol: 'cm', name: 'Centimeter' },
{ symbol: 'hectometer', name: 'Hectometer' },
{ symbol: 'chains', name: 'Chains' },
{ symbol: 'inch', name: 'Inch' },
{ symbol: 'foot', name: 'Feet' },
{ symbol: 'yard', name: 'Yard' },
{ symbol: 'mile', name: 'Mile' },
{ symbol: 'link', name: 'Link' },
{ symbol: 'rod', name: 'Rod' },
{ symbol: 'angstrom', name: 'Angstrom' },
{ symbol: 'mil', name: 'Mil'}
],
defaults: ['meter', 'cm']
},
liquid_volume: {
name: "Liquid Volume",
units: [
{ symbol: 'minim', name: 'Minim' },
{ symbol: 'fluiddram', name: 'Fluid Dram' },
{ symbol: 'fluidounce', name: 'Fluid Ounce' },
{ symbol: 'gill', name: 'Gill' },
{ symbol: 'cup', name: 'Cup' },
{ symbol: 'pint', name: 'Pint'},
{ symbol: 'quart', name: 'Quart'},
{ symbol: 'gallon', name: 'Gallon'},
{ symbol: 'beerbarrel', name: 'Beerbarrel'},
{ symbol: 'oilbarrel', name: 'Oilbarrel'},
{ symbol: 'hogshead', name: 'Hogshead'},
{ symbol: 'drop', name: 'Drop'},
],
defaults: ['minim', 'fluiddram']
},
mass: {
name: "Mass",
units: [
{ symbol: 'microgram', name: 'Microgram' },
{ symbol: 'kilogram', name: 'Kilogram' },
{ symbol: 'milligram', name: 'Milligram' },
{ symbol: 'gram', name: 'Gram' },
{ symbol: 'ton', name: 'Ton' },
{ symbol: 'grain', name: 'Grain' },
{ symbol: 'dram', name: 'Dram' },
{ symbol: 'ounce', name: 'Ounce' },
{ symbol: 'poundmass', name: 'Pound' },
{ symbol: 'hundredweight', name: 'Hundredweight' },
{ symbol: 'stick', name: 'Stick' },
{ symbol: 'stone', name: 'Stone' },
],
defaults: ['kilogram', 'gram']
},
power: {
name: "Power",
units: [
{ symbol: 'watt', name: 'Watt'},
{ symbol: 'hp', name: 'HP' }
],
defaults: ['watt', 'hp']
},
pressure: {
name: "Pressure",
units: [
{ symbol: 'Pa', name: 'Pascal' },
{ symbol: 'psi', name: 'PSI' },
{ symbol: 'atm', name: 'Atmospheres' },
{ symbol: 'torr', name: 'Torr' },
{ symbol: 'mmHg', name: 'mmHg' },
{ symbol: 'mmH2O', name: 'mmH2O' },
{ symbol: 'cmH20', name: 'cmH20' },
{ symbol: 'bar', name: 'Bars' },
],
defaults: ['Pa', 'psi']
},
temperature: {
name: "Temperature",
units: [
{ symbol: 'kelvin', name: 'Kelvin' },
{ symbol: 'celsius', name: 'Celsius' },
{ symbol: 'fahrenheit', name: 'Fahrenheit' },
{ symbol: 'rankine', name: 'Rankine' },
],
defaults: ['celsius', 'fahrenheit']
},
volume: {
name: "Volume",
units: [
{ symbol: 'litre', name: 'Litre' },
{ symbol: 'millilitre', name: 'Millilitre' },
{ symbol: 'hectolitre', name: 'Hectolitre' },
{ symbol: 'decalitre', name: 'Decalitre' },
{ symbol: 'deciliter', name: 'Deciliter' },
{ symbol: 'centilitre', name: 'Centilitre' },
{ symbol: 'cc', name: 'CC' },
{ symbol: 'cuin', name: 'Cuin' },
{ symbol: 'cuft', name: 'Cuft' },
{ symbol: 'cups', name: 'Cups' },
{ symbol: 'cuyd', name: 'Cubic Yard' },
{ symbol: 'pints', name: 'Pints' },
{ symbol: 'teaspoon', name: 'Teaspoon' },
{ symbol: 'tablespoon', name: 'Tablespoon' },
],
defaults: ['litre', 'millilitre']
},
} // Units
DDH.conversions.build = function(ops) {
// Defaults to length if no base is supported
var startBase = ops.data.physical_quantity || 'length';
var leftUnit = ops.data.left_unit || Units[startBase].defaults[0];
var rightUnit = ops.data.right_unit || Units[startBase].defaults[1];
var rawInput = ops.data.raw_input || '1';
var unitsSpecified = false;
return {
// anytime this is triggered, we default to a high signal
signal: "high",
onShow: function() {
DDG.require('math.js', function() {
// checks to see if custom units need set up and selectors cached
if(!localDOMInitialized) {
setUpLocalDOM();
Converter.setUpCustomUnits();
}
if(!initialized) {
Converter.updateUnitSelectors(startBase);
Converter.updateBaseUnitSelector(startBase);
// if no numbers provided, fall back on 1
if(!unitsSpecified) {
$convert_left.val(rawInput);
$select_left.val(leftUnit);
$select_right.val(rightUnit);
Converter.convert();
}
initialized = true;
}
$convert_left.keyup(function( _e ) {
if(this.value === "") {
$convert_right.val("");
}
if(this.value !== "" && $.isNumeric(this.value)) {
Converter.convert();
}
});
$convert_right.keyup(function( _e ) {
if(this.value === "") {
$convert_left.val("");
}
if(this.value !== "" && $.isNumeric(this.value)) {
Converter.convert("left");
}
});
$convert_left.click(function() {
this.select()
});
$convert_right.click(function() {
this.select()
});
$select_right.change(function() {
Converter.convert();
});
$select_left.change(function() {
Converter.convert();
});
// if the user changes the unit base
$unitSelector.change(function() {
Converter.updateUnitSelectors(this.value);
$convert_left.val("1");
Converter.convert();
});
});
}// on show
}; // return
}; // DDH.conversions.build
// checks we are not in the browser and exposes Converter for unit testing
if (typeof window === 'undefined') {
module.exports = Converter;
}
})(DDH);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,952 @@
---
aliases:
- oz
- ozs
- ounce
- ounces
type: mass
unit: ounce
symbols: [oz]
---
aliases:
- lbm
- pound mass
- lb
- lbs
- lbms
- pounds mass
- pound
- pounds
type: mass
unit: poundmass
symbols: [lb]
---
aliases:
- stones
- sts
- stone
- st
type: mass
unit: stone
symbols: [st]
---
aliases:
- kilo
- kilogramme
- kgs
- kilos
- kilogrammes
- kilograms
type: mass
unit: kilogram
symbols: [kg]
---
aliases:
- gm
- gramme
- gs
- gms
- grammes
type: mass
unit: gram
symbols: [g]
---
aliases:
- mg
- mgs
- milligram
- milligrams
- milli-gram
- milli-grams
type: mass
unit: milligram
symbols: [mg]
---
aliases:
- mcg
- mcgs
- microgram
- micrograms
type: mass
unit: microgram
symbols: [µg]
---
aliases:
- gs
- g
- gram
- grams
type: mass
unit: gram
symbols: [g]
---
aliases:
- stick
- sticks
type: mass
unit: stick
---
aliases:
- ton
- tons
- tonnes
- tonne
type: mass
unit: ton
---
aliases:
- grain
- grains
- gr
- troy grain
- troy grains
type: mass
unit: grain
---
aliases:
- hundredweight
- hundredweights
- hundred weight
- hundred weights
type: mass
unit: hundredweight
---
aliases:
- dram
- drams
- dram avoirdupois
- drams avoirdupois
- avoirdupois dram
type: mass
unit: dram
symbols: [dr]
---
aliases:
- metre
- metres
- meter
- meters
- m
type: length
unit: meter
symbols: [m]
---
aliases:
- megametre
- megametres
- Mms
type: length
unit: megameter
symbols: [Mm]
---
aliases:
- kilometre
- kilometres
- kilometer
- kilometers
- kilo meter
- kilo meters
- km
- kms
- klick
- klicks
type: length
unit: kilometer
symbols: [km]
---
aliases:
- hectometre
- hectometres
- hms
- hm
- hectometer
- hectometers
type: length
unit: hectometer
symbols: [hm]
---
aliases:
- decametre
- decametres
- dam
- dams
- decameter
- decameters
type: length
unit: decameter
symbols: [dam]
---
aliases:
- decimetre
- decimetres
- decimeter
- decimeters
- dms
type: length
unit: decimeter
symbols: [dm]
---
aliases:
- centimetre
- centimetres
- centimeter
- centimeters
- cm
- cms
type: length
unit: cm
symbols: [cm]
---
aliases:
- millimetre
- millimetres
- millimeter
- millimeters
- milli meter
- milli meters
- mm
- mms
type: length
unit: millimeter
symbols: [mm]
---
aliases:
- micrometre
- micrometres
- micrometer
- micrometers
- micro meter
- micro meters
- µms
type: length
unit: micrometer
symbols: [µm]
---
aliases:
- nanometre
- nanometres
- nanometer
- nanometers
- nano meter
- nano meters
- nano metre
- nano metres
- nm
- nms
type: length
unit: nanometer
symbols: [nm]
---
aliases:
- picometre
- picometres
- picometer
- picometers
- pm
- pms
type: length
unit: picometer
symbols: [pm]
---
aliases:
- mi
- statute mile
- statute miles
- land mile
- land miles
- mile
- miles
type: length
unit: mile
---
aliases:
- yd
- yds
- yrds
- yard
- yards
type: length
unit: yard
symbols: [yd]
---
aliases:
- angstrom
- ångström
- Å
type: length
unit: angstrom
---
aliases:
- ft
- international foot
- international feet
- survey foot
- survey feet
- foot
- feet
type: length
unit: foot
symbols: ["'"]
---
aliases:
- in
- ins
- inch
- inches
type: length
unit: inch
symbols: ['"']
---
aliases:
- gunter's chains
- chains
- chain
type: length
unit: chains
---
aliases:
- gunter's links
- links
- link
type: length
unit: link
---
aliases:
- rd
- rod
- rods
type: length
unit: rod
---
aliases:
- square hectometre
- square hectometres
- square hectometer
- square hectometers
- hectare
- hectares
type: area
unit: hectare
symbols: [ha]
---
aliases:
- acre
- acres
type: area
unit: acre
---
aliases:
- square millimeter
- square millimeters
- square millimetre
- square millimetres
- mm^2
type: area
unit: sqmil
symbols: [mm²]
---
aliases:
- square meter
- square meters
- squaremeter
- squaremeters
- square-meter
- square-meters
- squared meter
- squared meters
- squared-meter
- squared-meters
- squaredmeter
- squaredmeters
- m^2
- m2
type: area
unit: m2
---
aliases:
- sq mi
- square statute mile
- square statute miles
- square land mile
- square land miles
- miles^2
- miles²
- square mile
- square miles
type: area
unit: sqmi
---
aliases:
- yard^2
- yard²
- yards²
- yards^2
- yd^2
- yrd^2
- yrd²
- square yard
- square yards
- sqyd
type: area
unit: sqyd
symbols: [yd²]
---
aliases:
- feet^2
- feet²
- foot^2
- foot²
- ft²
- ft^2
- square foot
- square feet
- sqft
type: area
unit: sqft
---
aliases:
- inch^2
- inches^2
- squinch
- in^2
- in²
- square inch
- square inches
- squared inch
- squared inches
type: area
unit: sqin
---
aliases:
- liter
- liters
- l
- L
- litter
- litters
- litre
- litres
type: volume
unit: litre
symbols: [L]
---
aliases:
- hectolitre
- hectolitres
- hectoliter
- hectoliters
- hl
type: volume
unit: hectolitre
symbols: [hL]
---
aliases:
- decaliter
- decaliters
- dal
- decalitre
- decalitres
type: volume
unit: decalitre
symbols: [daL]
---
aliases:
- deciliter
- decilitre
- decilitres
- deciliters
- dl
- dL
type: volume
unit: deciliter
symbols: [dL]
---
aliases:
- centiliter
- centiliters
- centilitre
- centilitres
- cl
type: volume
unit: centilitre
symbols: [cL]
---
aliases:
- millilitre
- millilitres
- milliliter
- milliliters
- ml
type: volume
unit: millilitre
symbols: [mL]
---
aliases:
- cubic inch
- cubic in
- cu inch
- cu in
- inch^3
- in^3
- cui
type: volume
unit: cuin
---
aliases:
- pints
- pint
- uk pint
- british pint
- pts
- imperial pint
type: volume
unit: pints
---
aliases:
- cups
- cup
type: volume
unit: cup
---
aliases:
- metric tsp
- metric tsp.
- teaspoon
- teaspoons
type: volume
unit: teaspoon
---
aliases:
- metric tbsp
- metric tbsp.
- tablespoon
- tablespoons
type: volume
unit: tablespoon
---
aliases:
- days
- dy
- dys
- day
type: duration
unit: day
symbols: [d]
---
aliases:
- sec
- second
- seconds
type: duration
unit: second
symbols: [s]
---
aliases:
- millisec
- millisecs
- millisecond
- milliseconds
type: duration
unit: millisecond
symbols: [ms]
---
aliases:
- microsec
- microsecs
- microsecond
- microseconds
- micro second
- micro seconds
- micro-second
- micro-seconds
- µs
type: duration
unit: microsecond
symbols: [µs]
---
aliases:
- nanosec
- nanosecs
- nanosecond
- nanoseconds
- nano second
- nano seconds
- ns
type: duration
unit: nanosecond
symbols: [ns]
---
aliases:
- min
- mins
- minute
- minutes
type: duration
unit: minute
symbols: [min]
---
aliases:
- h
- hr
- hrs
- hour
- hours
type: duration
unit: hour
symbols: [h]
---
aliases:
- wks
- wk
- week
- weeks
type: duration
unit: week
---
aliases:
- mn
- mns
- mons
- month
- months
type: duration
unit: month
---
aliases:
- yr
- yrs
- year
- years
type: duration
unit: year
symbols: [a]
---
aliases:
- decade
- decades
type: duration
unit: decade
---
aliases:
- century
- centuries
type: duration
unit: century
---
aliases:
- millennia
- millennium
- millenniums
type: duration
unit: millennium
---
aliases:
- pa
- pas
- pascals
type: pressure
unit: Pa
symbols: [Pa]
---
aliases:
- atm
- atms
- atmosphere
- atmospheres
type: pressure
unit: atm
---
aliases:
- psis
- psi
- lbs/inch^2
- p.s.i.
- p.s.i
- pound per square inch
- pounds per square inch
type: pressure
unit: psi
---
aliases:
- mmhg
type: pressure
unit: mmHg
symbols: [mmHg]
---
aliases:
- tor
- torr
type: pressure
unit: torr
---
aliases:
- bar
- bars
type: pressure
unit: bar
---
aliases:
- js
- joule
- joules
type: energy
unit: joule
symbols: [J]
---
aliases:
- kilojs
- kilojoule
- kilojoules
- kilo-joule
- kilo-joules
type: energy
unit: kilojoule
symbols: [J]
---
aliases:
- watt hour
- watt hours
- watt-hour
- watt-hours
- Wh
type: energy
unit: Wh
symbols: [Wh]
---
aliases:
- ergon
- ergons
- erg
- ergs
type: energy
unit: erg
---
aliases:
- electronvolt
- electronvolts
- electron volt
- electron volts
- evs
- eV
type: energy
unit: electronvolt
symbols: [eV]
---
aliases:
- btus
- BTU
- btu
- british thermal unit
- british thermal units
type: energy
unit: BTU
symbols: [BTU]
---
aliases:
- gram calorie
- gram calories
- gramcalories
- gramcalorie
type: energy
unit: gramcalorie
---
aliases:
- kilo calorie
- kilo calories
- kilocalories
- kilocalorie
type: energy
unit: kilocalorie
---
aliases:
- watt
- watts
type: power
unit: watt
symbols: [W]
---
aliases:
- metric horsepowers
- mhp
- hp
- cv
- hk
- ks
- ch
- metric horsepower
- mechanical horsepower
- mechanical horsepowers
- PS
type: power
unit: hp
---
aliases:
- deg
- degs
- degrees
- degree
type: angle
unit: deg
symbols: [°]
---
aliases:
- rads
- radian
- radians
type: angle
unit: rad
symbols: [rad]
---
aliases:
- milliradian
- milliradians
- milli-radian
- milli-radians
- millirad
- millirads
type: angle
unit: millirad
---
aliases:
- grad
- grads
- gon
- gons
- grade
- grades
- gradian
- gradians
type: angle
unit: grad
---
aliases:
- newton
- newtons
type: force
unit: newton
symbols: [N]
---
aliases:
- dynes
- dyne
type: force
unit: dyne
---
aliases: []
type: force
unit: kilodyne
---
aliases:
- lbs force
- lb force
- pound force
- pounds force
- poundforce
- poundsforce
type: force
unit: poundforce
---
aliases:
- f
- farenheit
- degrees f
- degrees farenheit
can_be_negative: 1
type: temperature
unit: fahrenheit
symbols: [°f]
---
aliases:
- c
- centigrade
- degrees c
- degrees celsius
can_be_negative: 1
type: temperature
unit: celsius
symbols: [°c]
---
aliases:
- kelvin
- kelvins
type: temperature
unit: kelvin
symbols: [K]
---
aliases:
- r
- Ra
- rankine
type: temperature
unit: rankine
symbols: [°Ra]
---
aliases:
- b
- bit
- bits
type: digital
unit: b
---
aliases:
- B
- byte
- bytes
type: digital
unit: B
---
aliases:
- kilobit
- kilobits
type: digital
unit: kbit
---
aliases:
- megabit
- megabits
type: digital
unit: mbit
---
aliases:
- gigabit
- gigabits
type: digital
unit: gbit
---
aliases:
- terrabit
- terrabits
type: digital
unit: tbit
---
aliases:
- KB
- KBs
- kilobyte
- kilobytes
type: digital
unit: KB
---
aliases:
- MB
- MBs
- megabyte
- megabytes
type: digital
unit: MB
---
aliases:
- GB
- GBs
- gigabyte
- gigabytes
type: digital
unit: GB
---
aliases:
- TB
- TBs
- terabyte
- terabytes
type: digital
unit: TB

98
spec/conversions_spec.js Normal file
View File

@ -0,0 +1,98 @@
GLOBAL.DDH = {};
var math = require("mathjs");
var Converter = require("../share/goodie/conversions/conversions.js");
describe("Conversion of Custom Units", function() {
// set up the custom units
Converter.setUpCustomUnits();
/**
* CUSTOM DIGITAL UNITS
*/
it("should convert gb to mb", function() {
var conversion = Converter.eval("2GB to MB");
expect(conversion).toEqual("2000");
});
it("should convert TB to MB", function() {
var conversion = Converter.eval("8TB to MB");
expect(conversion).toEqual("8e+6");
});
it("should convert GB to TB", function() {
var conversion = Converter.eval("1000GB to TB");
expect(conversion).toEqual("1");
});
it("should convert GB to TB", function() {
var conversion = Converter.eval("100GB to TB");
expect(conversion).toEqual("0.1");
});
it("should convert TB to GB", function() {
var conversion = Converter.eval("1TB to GB");
expect(conversion).toEqual("1000");
});
it("should convert MB to TB", function() {
var conversion = Converter.eval("3500MB to TB");
expect(conversion).toEqual("0.0035");
});
it("should convert PB to TB", function() {
var conversion = Converter.eval("5PB to TB");
expect(conversion).toEqual("5000");
});
it("should convert PB to GB", function() {
var conversion = Converter.eval("7PB to GB");
expect(conversion).toEqual("7e+6");
});
it("should convert PB to GB", function() {
var conversion = Converter.eval("7PB to GB");
expect(conversion).toEqual("7e+6");
});
it("should convert MB to gbits", function() {
var conversion = Converter.eval("6500MB to gbit");
expect(conversion).toEqual("52");
});
it("should convert mbits to gbits", function() {
var conversion = Converter.eval("100000mbit to gbit");
expect(conversion).toEqual("100");
});
it("should convert tbits to mbits", function() {
var conversion = Converter.eval(".5tbit to mbit");
expect(conversion).toEqual("5e+5");
});
/**
* CUSTOM ENERGY UNITS
*/
it("should convert joules to kilojoules", function() {
var conversion = Converter.eval("8888joules to kilojoule");
expect(conversion).toEqual("8.888");
});
it("should convert joules to kilojoules", function() {
var conversion = Converter.eval("34311joules to kilojoule");
expect(conversion).toEqual("34.311");
});
it("should convert gram calories to kilojoules", function() {
var conversion = Converter.eval("34311323gramcalorie to kilojoule");
expect(conversion).toEqual("1.43559e+5");
});
it("should convert kilocalorie to kilojoules", function() {
var conversion = Converter.eval("6543kilocalorie to kilojoule");
expect(conversion).toEqual("27375.9");
});
});

View File

@ -8,4 +8,4 @@
],
"stopSpecOnExpectationFailure": false,
"random": false
}
}

File diff suppressed because it is too large Load Diff