diff --git a/app/static/app/js/classes/Units.js b/app/static/app/js/classes/Units.js index 0885cc2c..88c8376c 100644 --- a/app/static/app/js/classes/Units.js +++ b/app/static/app/js/classes/Units.js @@ -3,7 +3,8 @@ import { _ } from './gettext'; const types = { LENGTH: 1, AREA: 2, - VOLUME: 3 + VOLUME: 3, + TEMPERATURE: 4 }; const units = { @@ -139,6 +140,26 @@ const units = { round: 4, label: _("Cubic Yards"), type: types.VOLUME + }, + celsius:{ + conversion:{ + forward: celsius => celsius, + backward: celsius => celsius + }, + abbr: '°C', + round: 1, + label: _("Celsius"), + type: types.TEMPERATURE + }, + fahrenheit:{ + conversion: { + forward: celsius => (9.0 / 5.0) * celsius + 32.0, + backward: fahrenheit => (fahrenheit - 32.0) * (5.0 / 9.0) + }, + abbr: '°F', + round: 1, + label: _("Fahrenheit"), + type: types.TEMPERATURE } }; @@ -175,6 +196,7 @@ class UnitSystem{ lengthUnit(meters, opts = {}){ throw new Error("Not implemented"); } areaUnit(sqmeters, opts = {}){ throw new Error("Not implemented"); } volumeUnit(cbmeters, opts = {}){ throw new Error("Not implemented"); } + temperatureUnit(celsius, opts = {}){ throw new Error("Not implemented"); } getName(){ throw new Error("Not implemented"); } getKey(){ throw new Error("Not implemented"); } @@ -209,6 +231,15 @@ class UnitSystem{ const val = unit.factor * cbmeters; return new ValueUnit(val, unit); } + + temperature(celsius, opts = {}){ + celsius = parseFloat(celsius); + if (isNaN(celsius)) return NanUnit(); + + const unit = this.temperatureUnit(celsius, opts); + const val = unit.conversion.forward(celsius); + return new ValueUnit(val, unit); + } }; function toMetric(valueUnit, unit){ @@ -221,13 +252,23 @@ function toMetric(valueUnit, unit){ } if (isNaN(value)) return NanUnit(); - const val = value / unit.factor; + let val; + if (unit.factor !== undefined){ + val = value / unit.factor; + }else if (unit.conversion !== undefined){ + val = unit.conversion.backward(value); + }else{ + throw new Error(`No unit factor or conversion: ${unit.type}`); + } + if (unit.type === types.LENGTH){ return new ValueUnit(val, units.meters); }else if (unit.type === types.AREA){ return new ValueUnit(val, unit.sqmeters); }else if (unit.type === types.VOLUME){ return new ValueUnit(val, unit.cbmeters); + }else if (unit.type === types.TEMPERATURE){ + return new ValueUnit(val, units.celsius); }else{ throw new Error(`Unrecognized unit type: ${unit.type}`); } @@ -261,6 +302,10 @@ class MetricSystem extends UnitSystem{ volumeUnit(cbmeters, opts = {}){ return units.cbmeters; } + + temperatureUnit(celsius, opts = {}){ + return units.celsius; + } } class ImperialSystem extends UnitSystem{ @@ -316,6 +361,10 @@ class ImperialSystem extends UnitSystem{ volumeUnit(cbmeters, opts = {}){ return this.cbyards(); } + + temperatureUnit(celsius, opts = {}){ + return units.fahrenheit; + } } class ImperialUSSystem extends ImperialSystem{ diff --git a/app/static/app/js/components/tests/Units.test.jsx b/app/static/app/js/components/tests/Units.test.jsx index 174b38aa..4aed9a5a 100644 --- a/app/static/app/js/components/tests/Units.test.jsx +++ b/app/static/app/js/components/tests/Units.test.jsx @@ -50,6 +50,15 @@ describe('Metric system', () => { }); expect(metric.area(11005.09, { fixedUnit: true }).toString({precision: 1})).toBe("11,005.1 m²"); + + const temperatures = [ + [1, "1 °C"], + [100.255, "100.3 °C"] + ]; + + temperatures.forEach(v => { + expect(metric.temperature(v[0]).toString()).toBe(v[1]); + }); }) }); @@ -98,6 +107,15 @@ describe('Imperial systems', () => { }); expect(imperial.area(9999, { fixedUnit: true }).toString({precision: 1})).toBe("107,628.3 ft²"); + + const temperatures = [ + [1, "33.8 °F"], + [100.255, "212.5 °F"] + ]; + + temperatures.forEach(v => { + expect(imperial.temperature(v[0]).toString()).toBe(v[1]); + }); }); }); @@ -118,5 +136,13 @@ describe('Metric conversion', () => { expect(toMetric(km).value).toBe(2000); expect(toMetric(mi).value).toBe(3220); + + const celsius = metric.temperature(50); + const fahrenheit = imperial.temperature(50); + + expect(celsius.unit.abbr).toBe("°C"); + expect(fahrenheit.unit.abbr).toBe("°F"); + expect(toMetric(celsius).value).toBe(50); + expect(toMetric(fahrenheit).value).toBe(50); }); });