improved unit conversion and tests
This commit is contained in:
@ -1,18 +1,9 @@
|
||||
from django.core.cache import caches
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
from cookbook.helper.cache_helper import CacheHelper
|
||||
from cookbook.models import Ingredient, Unit
|
||||
|
||||
# basic units that should be considered for "to" conversions
|
||||
# TODO possible remove this hardcoded units and just add a flag to the unit
|
||||
CONVERT_TO_UNITS = {
|
||||
'metric': ['g', 'kg', 'ml', 'l'],
|
||||
'us': ['ounce', 'pound', 'fluid_ounce', 'pint', 'quart', 'gallon'],
|
||||
'uk': ['ounce', 'pound', 'imperial_fluid_ounce', 'imperial_pint', 'imperial_quart', 'imperial_gallon'],
|
||||
}
|
||||
|
||||
CONVERSION_TABLE = {
|
||||
'weight': {
|
||||
'g': 1000,
|
||||
@ -38,8 +29,8 @@ CONVERSION_TABLE = {
|
||||
},
|
||||
}
|
||||
|
||||
BASE_UNITS_WEIGHT = CONVERSION_TABLE['weight'].keys()
|
||||
BASE_UNITS_VOLUME = CONVERSION_TABLE['volume'].keys()
|
||||
BASE_UNITS_WEIGHT = list(CONVERSION_TABLE['weight'].keys())
|
||||
BASE_UNITS_VOLUME = list(CONVERSION_TABLE['volume'].keys())
|
||||
|
||||
|
||||
class ConversionException(Exception):
|
||||
@ -58,6 +49,13 @@ class UnitConversionHelper:
|
||||
|
||||
@staticmethod
|
||||
def convert_from_to(from_unit, to_unit, amount):
|
||||
"""
|
||||
Convert from one base unit to another. Throws ConversionException if trying to convert between different systems (weight/volume) or if units are not supported.
|
||||
:param from_unit: str unit to convert from
|
||||
:param to_unit: str unit to convert to
|
||||
:param amount: amount to convert
|
||||
:return: Decimal converted amount
|
||||
"""
|
||||
system = None
|
||||
if from_unit in BASE_UNITS_WEIGHT and to_unit in BASE_UNITS_WEIGHT:
|
||||
system = 'weight'
|
||||
@ -87,7 +85,7 @@ class UnitConversionHelper:
|
||||
# TODO allow setting which units to convert to? possibly only once conversions become visible
|
||||
units = caches['default'].get(CacheHelper(self.space).BASE_UNITS_CACHE_KEY, None)
|
||||
if not units:
|
||||
units = Unit.objects.filter(space=self.space, base_unit__in=(CONVERT_TO_UNITS['metric'] + CONVERT_TO_UNITS['us'] + CONVERT_TO_UNITS['uk'])).all()
|
||||
units = Unit.objects.filter(space=self.space, base_unit__in=(BASE_UNITS_VOLUME + BASE_UNITS_WEIGHT)).all()
|
||||
caches['default'].set(CacheHelper(self.space).BASE_UNITS_CACHE_KEY, units, 60 * 60) # cache is cleared on unit save signal so long duration is fine
|
||||
|
||||
for u in units:
|
||||
@ -112,13 +110,15 @@ class UnitConversionHelper:
|
||||
conversions = [ingredient]
|
||||
if ingredient.unit:
|
||||
for c in ingredient.unit.unit_conversion_base_relation.all():
|
||||
r = self._uc_convert(c, ingredient.amount, ingredient.unit, ingredient.food)
|
||||
if r and r not in conversions:
|
||||
conversions.append(r)
|
||||
if c.space == self.space:
|
||||
r = self._uc_convert(c, ingredient.amount, ingredient.unit, ingredient.food)
|
||||
if r and r not in conversions:
|
||||
conversions.append(r)
|
||||
for c in ingredient.unit.unit_conversion_converted_relation.all():
|
||||
r = self._uc_convert(c, ingredient.amount, ingredient.unit, ingredient.food)
|
||||
if r and r not in conversions:
|
||||
conversions.append(r)
|
||||
if c.space == self.space:
|
||||
r = self._uc_convert(c, ingredient.amount, ingredient.unit, ingredient.food)
|
||||
if r and r not in conversions:
|
||||
conversions.append(r)
|
||||
|
||||
conversions = self.base_conversions(conversions)
|
||||
|
||||
|
Reference in New Issue
Block a user