A proper unit system
Currently, there is a small bit of code in recipes that knows just enough to recognize certain strings (such as "kg", "lbs" or "min") as units.
A proper unit system will handle:
- Conversion between different units for the same dimension (e.g. from grams to kilograms)
- Units for weight, volume, time, temperature
- Translation of unit names according to locale
- Heuristics for preferred units for display (e.g. "2.5 kg" is preferred over "2500000 milligram")
- Human-friendly display (e.g. "2 2/3 kg" instead of "2.66667 kg")
- Many cooking units that we currently ignore (such as various spoons)
We probably don't need to support the full dimension algebra (ie derive conversions for things like km/h -> m/s).
1. Details
Here is a step-by-step outline for how I envision this work to proceed.
- Classify units as mass or volume (or other) units - I think this will need to be added to the unit information in gr-unit.c, and we probably need to introduce a struct for units.
Create a matrix of conversions for mass units. See krecipes-mass-conversions.png for inspiration (not an inspiration for the desired UI, notabene)
- Implement an api to convert values between units, using this matrix. This could like like this:
gboolean gr_unit_convert (GrNumber *in, GrUnit *from, GrUnit *to, GrNumber *out)
The boolean return value will be used to indicate when a conversion is not possible.
- Write unit tests for this new API
Explore if we can drop the GrNumber class while preserving human-friendly mixed-fraction formatting. This would greatly simplify the code. This should be backed by tests to verify the expected formatting
- If yes, the unit conversion api can be simplified to work directly with doubles
- Add a imperial vs. metric preference. This preference can also be used for temperature conversion between Fahrenheit and Celsius. We will need to consult our designers to figure out how this should work in the UI, exactly. It could be a traditional preference dialog, or a toggle in the recipe details UI.
- Apply this when displaying ingredients in the details page and in the shopping list.
- Research the heuristics that gourmet applies to determine display units
- Implement a similar heuristic
- Write tests for this
- Apply it when displaying units
- Add a unit conversion utility to the app. We will need a mockup for this, from our designers.
Do the same for volume units. See krecipes-volume-conversions.png for inspiration
- Compare our set of units with the units in gourmet and krecipes and add the ones we're missing
- Research what is needed to allow conversions between mass and volume units (density information for ingredients)
Updates (June 27):
The switch from GrNumber to doubles was done (by Matthias), so we can just operate on doubles now. Conversion to fractions is done for display only
- We ended up using the locale facet NL_MEASUREMENT_MEASUREMENT for temperature conversion, so we may not need a imperial/metric preference in the UI
- An idea that we've discussed as a next step after basic conversion is to avoid awkward fractional numbers and display approximate rounded values instead, with an indicator, and allow revealing the exact values somehow. Design input needed
- Further on, for temperatures, we may need a way to annotate the original temperature as 'must be exact', and avoid rounding in that case