gentooboontoo / js-quantities

JavaScript library for quantity calculation and unit conversion
http://gentooboontoo.github.io/js-quantities/
MIT License
396 stars 102 forks source link

Problems with using js-quantities to parse engineering input #12

Open evantandersen opened 10 years ago

evantandersen commented 10 years ago

I'm trying to use js-quantities to parse input for an engineering simulation. I want users to enter input in any units by writing both the unit value and name. Ex, for a weight field, all of these would be acceptable:

160 kg
40 lbs
200 pound
14 microgram

This works by doing: (new Qty(element.val())).to("kg").scalar!

However, I have problems with a few other fields in my app:

Torque

While torque is supported, as it has the same dimension as energy, js-quantities will accept units of energy in a torque field. Additionally, while the dimension of lb ft is technically incorrect, torque is often expressed in these units (just look at any american automotive brochure)

new Qty('12 W h').to('N m').scalar;
43200

new Qty('278 lb ft').to('N m').scalar; //copied input string from ford.com
"Incompatible units"

Namespace collisions

The temperature field should naturally support the units C, F and K. Because of namespace collisions with farads and coulombs, temperature units are prepended with "temp", ie "tempC". This is not intuitive. Additionally, js-quantities will convert a temperature difference to an absolute temperature without error:

new Qty('12 degC').to('tempC').scalar;
-261.15

This is problematic, because to a user, "degC" actually sounds more correct than "tempC" because the common phrase is "degrees celsius". Ideally, valid inputs would include:

14.5 C
88 F
321 K

Derived unit parsing

Derived units require spaces between their components. This is not intuitive.

new Qty('12 kWh').to('J').scalar;
"Unit not recognized"

new Qty('12 Ah').to('C').scalar;
"Unit not recognized"

Conclusions

All of these problems stem from js-quantities not accepting any context about what unit it's trying to parse. This seems to suggest I am using this library for something it was not intended to do. I thought I'd post these gripes here because @gentooboontoo recently commented on a stackoverflow question, but I don't expect these to be fixed. I'm now looking at either finding another library or forking this one to make the changes I need.

rage-shadowman commented 10 years ago

This seems like it should have been a few separate tickets. Or maybe a blog post.

This library is a port of https://github.com/olbrich/ruby-units.

Conclusion: Yes, it looks like you are trying to do something that js-quantities was not intended to do. It was intended to convert values between 2 compatible unambiguous unit types, and it does that very well (my team is using it in production to convert weather station data to localized values). It was not intended to be used to guess a user's intention and decide what they really wanted was X despite what they asked for. For that you'll want to use Google. ;)

PS - If you do come up with a good (unit testable) new constructor, I would definitely be interested in merging it into my fork (and who knows, @gentooboontoo might merge it too). However, the unit tests would need to be thorough (possibly generated programmatically by looping through all possible unit types with and without prefixes and joining them to determine which ones are ambiguous -- there might not be many, but there definitely are some).

rage-shadowman commented 10 years ago

Looks like I'm wrong, lbf is pound-force not pound-foot maybe it's lbf*ft that is wanted? Which also explains why you said force (meaning torque) is compatible with energy (so not a bug). And there doesn't seem to be a simple way to differentiate torque from energy here.

sheam commented 7 years ago

Any update on js-quantities being able to handle torque?

librilex commented 7 years ago

No updates, but it already works out of the box:

Qty('1 N*m').to('lbf*ft') // outputs a quantity of roughly '0.74 lbf*ft'

One could add the unit 'Nm' though:

var UNITS = {
  // ... //
  /* torque */
  "<Newton-meter>" : [["Nm"], 1.0, "energy", ["<kilogram>","<meter>","<meter>"], ["<second>","<second>"]],
  // ... //
};