Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compound unit support? #10

Open
woahdae opened this issue May 14, 2016 · 5 comments
Open

Compound unit support? #10

woahdae opened this issue May 14, 2016 · 5 comments

Comments

@woahdae
Copy link

woahdae commented May 14, 2016

I'm working on a sideproject that needs a lot of custom conversions, which is why I like ruby-measurement over ruby-units; the latter's code takes quite a lot of staring to grok, and ultimately the conversions are hard-coded, which I found odd (but maybe I don't know the problemspace well enough?).

In any case, ruby-measurement's code is easy to read and defining custom conversions is a no-brainer.

However, most of the units and conversions I'm working with are compound, like converting pounds/acre to oz/sq ft. For now I'll just define custom units and conversions for all the variations I'm using (not too onerous), but is there planned support for compound units that's more clever than brute-force defining every possibility?

@mhuggins
Copy link
Owner

That sounds like a solid use case for defining custom units & conversions. I think there are too many potential compound units to try to include them in the gem itself.

@mhuggins
Copy link
Owner

As a quick example:

Measurement.define(:"lbs/ac") do |unit|
  unit.alias :"lbs./ac.", :"pounds/acre"
  unit.convert_to(:"oz/sq ft") { |value| value / 2722.5 }
end

Measurement.define(:"oz/sq ft") do |unit|
  unit.alias :"oz/sq. ft.", :"oz/sq ft."
  unit.convert_to(:"lbs/ac") { |value| value * 2722.5 }
end

@woahdae
Copy link
Author

woahdae commented May 14, 2016

Here's what it currently looks like, and I think you can see where official support for understanding numerators and denominators would be nice:

Measurement.define('acre') do |unit|
  unit.alias 'ac'
  unit.convert_to('sq ft') { |value| value * 43560}
end

Measurement.define('lb/ac') do |unit|
  unit.alias "lb / ac", "lbs/ac", 'lb/acre', 'lbs/acre', 'lb / acre', 'lbs / acre', 'lbs / acre', "lbs / ac", "lb per acre", "lbs per acre"
  unit.convert_to('lb/sq ft') {|value| value / 43560}
  unit.convert_to('oz/sq ft') {|value| value / 43560 / 16}
  unit.convert_to('ppm') {|value| value / 2}
end

Measurement.define('lb/sq ft') do |unit|
  unit.alias "lb / sq ft", "lbs/sq ft", "lbs / sq ft", "lb per square foot", "lbs per square foot"
  unit.convert_to('lb/ac') {|value| value * 43560}
  unit.convert_to('oz/sq ft') {|value| value * 16}
  unit.convert_to('ppm') {|value| value / 2 * 43560}
end

Measurement.define('oz/sq ft') do |unit|
  unit.alias "oz / sq ft", "ounces/sq ft", "oz per square foot", "ounces per square foot"
  unit.convert_to('lb/ac') {|value| value * 43560 / 16}
  unit.convert_to('lb/sq ft') {|value| value / 16}
  unit.convert_to('ppm') {|value| value * 43560 / 16 / 2}
end

Measurement.define('ppm') do |unit|
  unit.convert_to('lb/ac') {|value| value * 2}
  unit.convert_to('lb/sq ft') {|value| value * 2 / 43560}
  unit.convert_to('oz/sq ft') {|value| value * 2 / 43560 / 16}
end

And I just covered a few of the common aliases. The number of aliases for a compound unit is numerator aliases * denominator aliases * [space variations around '/'] * 2 ["per"], if you want to support compound unit aliases.

Plus, clearly, for many conversions I'm using a base unit as part of the calculation, and it's at least error-prone to enumerate all the definitions like this. If you knew the relationship between the numerators and denominators separately, you could just define the conversion of an acre to square feet (for example), and we already know the rest.

Finally, 'ppm' is a great example of a sticking point, but also a strength of your library. 'ppm' is a compound unit translating to pounds-per-acre just for my problemspace. But, I think someone could come up with a way of defining that conversion and having the rest fall out. It might need knowledge of unit categories, for example, defining 'ppm' -> 'lb/sq ft' lets it be known that ppm converts to weight/volume. So, that's a tough one.

@woahdae
Copy link
Author

woahdae commented May 14, 2016

Oh, and of course, multiplying compound units needs official support (or hacks on my end). Ex: Measurement.parse("10 lbs/acre") * Measurement.parse("2 acres") should yield 20 lbs (or even more useful, Measurement.parse("10 lbs/acre") * Measurement.parse("1 sq ft") should yield 0.000229568 lbs), but the concept of "converting" lbs/acre to lbs doesn't really make sense, right?

I might need to end up writing a lot of custom conversion logic for my problemspace anyways, so maybe I'll have more insight on how to model this at some later point.

@mhuggins
Copy link
Owner

The math part of your argument makes sense. I think multiplying compound units and getting a new unit would be a great feature. It's a big undertaking though, and with my focus on other things at the moment, I don't see it being a feature that I get to unfortunately. With that said, it's something that I would be happy to support if you or someone else felt like contributing to the gem!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants