diff --git a/README.md b/README.md index 21764a3..65f0c70 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ npm install node-units * `importDB(file_name, cb)` - imports a custom unit database, `cb` takes a single argument `err` * `importDBSync(file_name)` - the sync version of `importDB` * `getDB()` - returns he currently used database of units as an object -* `convert(type, value, from, to)` - converts `value` of `from` to `to`, returns the result or raises exception if conversion cannot be made +* `convert(conversion_string)` - where `conversion_string` is of the form ` to ` ### Properties * `types` - `types` is an object containing constants for each unit group. @@ -31,10 +31,10 @@ npm install node-units ```javascript var units = require('node-units'); -var result = units.convert('volume', 5, 'gill', 'mL'); +var result = units.convert('5 gills to mL'); // result == 591.4705 -units.convert(units.types.TIME, 5, 'day', 'second'); +units.convert('five days to seconds'); ``` ### Custom Units @@ -42,9 +42,9 @@ units.convert(units.types.TIME, 5, 'day', 'second'); With `node-units` you can import custom unit definitions from files defined like the following: ``` group: - long_name,longname,ln 1ln - another_unit,au 5ln - one_more,om 2au + longname,longname,ln 1ln + anotherunit,au 5ln + onemore,om 2au ``` ```javascript @@ -52,7 +52,7 @@ var units = require('node-units'); units.importDBSync('my_custom.units'); -var result = units.convert(units.types.GROUP, 5, 'au', 'one_more'); +var result = units.convert('five au to onemores'); // result == 10 ``` @@ -68,7 +68,7 @@ var units = require('node-units'); units.importDBSync('my_custom.units'); -var result = units.convert('time', 5, 'minute', 's'); +var result = units.convert('5 minutes to s'); // result == 250 ``` diff --git a/examples/custom/index.js b/examples/custom/index.js new file mode 100644 index 0000000..c76b27f --- /dev/null +++ b/examples/custom/index.js @@ -0,0 +1,10 @@ +var path = require('path'); +var units = require('../../'); + +var db = path.join(path.dirname(module.filename), 'my_custom.units'); +units.importDBSync(db); + +console.log(units.convert('5 buttons to widgets')); + + +console.log(units.convert('30 jings to jong')); diff --git a/examples/custom/my_custom.units b/examples/custom/my_custom.units new file mode 100644 index 0000000..8fd0bf5 --- /dev/null +++ b/examples/custom/my_custom.units @@ -0,0 +1,9 @@ +elements: + button,btn 5wg + widget,wg 2tbl + table,tbl 1tbl + +things: + jing 2jabber + jabber 30jong + jong 1jong diff --git a/examples/simple/index.js b/examples/simple/index.js new file mode 100644 index 0000000..4f85b04 --- /dev/null +++ b/examples/simple/index.js @@ -0,0 +1,13 @@ +var units = require('../../'); + +var result = units.convert('20 quarts to gallons'); + +console.log(result === 5); + + +try{ + var value = units.convert('5 days to gallon'); + console.log(value); +} catch(e){ + console.log(e); +} diff --git a/lib/default.units b/lib/default.units index c0c2c03..4140e12 100644 --- a/lib/default.units +++ b/lib/default.units @@ -7,9 +7,9 @@ time: volume: liter,L 1L milliliter,mL 0.001L - gallon,gal 3.78541L - pint 0.473176L - quart,qt 0.946353L + gallon,gal 8pint + pint 0.125gal + quart,qt 2pint tablespoon,tbl 0.03125pint teaspoon,tsp 0.33333333333tbl cup 16tbl diff --git a/lib/index.js b/lib/index.js index 95d0364..b1abe82 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,11 +1,16 @@ var path = require('path'); var fs = require('fs'); +var numerizer = require('numerizer'); var types = {}; +var conversion_regex = /^(.*?)\s([a-zA-Z]+)\sto\s([a-zA-Z]+)$/i; + var db_regex = /[a-zA-Z]+:\n([\s\t]+([a-zA-Z]+,?)+[\s\t]+[0-9.]+[a-zA-Z]+\n)+/g; var unit_database = {}; +var forms = [/s$/i, /es$/i, /ies$/i]; + var parseSection = function(section){ var lines = section.split('\n'); var section_name = lines.shift(); @@ -23,12 +28,12 @@ var parseSection = function(section){ var names = next[0].replace(/[\s\t]/g, '').split(','); var value = next[1].replace(/[\s\t]/g, '').match(/([0-9.]+)|([a-zA-Z]+)/g); - var unit = value[1]; + var unit = value[1].toLowerCase(); value = parseFloat(value[0]); names.forEach(function(name){ - unit_database[section_name][name] = {'unit': unit, - 'value': value}; + unit_database[section_name][name.toLowerCase()] = {'unit': unit, + 'value': value}; }); } }; @@ -81,6 +86,26 @@ var convert = function(type, value, from, to, max_calls){ }; +var get_variations = function(unit){ + var variations = [unit]; + forms.forEach(function(form){ + if(unit.match(form)){ + variations.push(unit.replace(form, '')); + } + }); + return variations; +}; + + +var determine_type = function(variations){ + for(var i in types){ + for(var k in variations){ + if(unit_database[types[i]][variations[k]] !== undefined){ + return {'type': types[i], 'unit': variations[k]}; + } + } + } +}; var default_db = path.join(path.dirname(module.filename), 'default.units'); importDBSync(default_db); @@ -92,20 +117,43 @@ return module.exports = { getDB: function(){ return unit_database; }, - convert: function(type, value, from, to){ - type = type.toLowerCase(); - - if(unit_database[type] == undefined){ - throw 'Unit group ' + type + ' does not exist'; - } else if(unit_database[type][from] == undefined){ - throw 'Unit ' + from + ' does not belong to unit group ' + type; - } else if(unit_database[type][to] == undefined){ - throw 'Unit ' + to + ' does not belong to unit group ' + type; + convert: function(str){ + var type, value, from, to, max_tries; + + var parts = conversion_regex.exec(str); + if(parts == null){ + throw 'Invalid conversion string: "' + str + '", expected " to "'; + return; + } + + value = parseFloat(numerizer(parts[1])); + var from_variations = get_variations(parts[2].toLowerCase()); + var to_variations = get_variations(parts[3].toLowerCase()); + + var from_type = determine_type(from_variations); + var to_type = determine_type(to_variations); + + if(!from_type){ + throw 'Unknown unit: "' + parts[2] + '"'; + return; } + if(!to_type){ + throw 'Unknown unit: "' + parts[3] + '"'; + return; + } + + if(from_type.type !== to_type.type){ + throw 'Units "' + from_type.unit + '" and "' + to_type.unit + '" do not belong in the same unit group'; + return; + } + + type = from_type.type; + from = from_type.unit; + to = to_type.unit; - var result = convert(type, value, from, to, 5); + var result = convert(type, value, from, to, max_tries); if(result == undefined){ - throw 'Conversion of ' + from + ' to ' + to + ' was not possible'; + throw 'Conversion of "' + from + '" to "' + to + '" was not possible'; } else{ return result; } diff --git a/package.json b/package.json index 5448ca1..a51af27 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-units", - "version": "0.1.0", + "version": "0.1.1", "description": "Node.JS unit conversion library with customizable units", "main": "lib/index.js", "directories": { @@ -21,5 +21,11 @@ "conversion" ], "author": "Brett Langdon (www.brett.is)", - "license": "MIT" + "license": "MIT", + "dependencies": { + "numerizer": "0.0.2" + }, + "devDependencies": { + "mocha": "*" + } }